sql - 如何存档一个巨大的 postgres 表?

标签 sql postgresql

我们有一个名为 history 的 postgres 表,它几乎有 900GB,而且每天还在不断增加 10GB。 这是一个微服务(购物车)正在访问的表。我们有 postgres 复制设置(一个主服务器和一个从服务器)。 2 个微服务实例正在生产中运行,其中 1 个实例使用主 postgres 连接为某些端点写入和​​读取数据 和 1 另一个实例正在使用 postgres 从属连接来单独读取数据。

表定义:

id - uuid
data - jsonb column
internal - jsonb column
context - jsonb column
created_date - date
modified_date - date

现在在上表中,datainternal 列的每一行都加载了大 json。我们已经得出关于将 datainternal 清空的结论 column 将减少该表的总空间消耗。

问题:

  1. 如何归档这个巨大的表? (意味着仅清理 datainternal 列)。
  2. 如何在不出现零停机时间/性能下降的情况下实现这一目标?

截至目前已测试的方法。

  1. 使用 pg_repack(这是迄今为止最好的主意,但这里的问题是一旦 pg_repack 完成,整个新表需要与从属实例同步,这会导致 WAL 开销)。
  2. 只需单独取消 datainternal 列 - 由于 postgres 遵循 MVCC 模式,这种方法的问题只是增加了表的大小。
  3. 使用临时表并克隆数据
    • 创建一个 UNLOGGED 表 - historyv2
    • 不带datainternal将原表中的数据复制到historyv2表中
    • 然后将表格切换到 LOGGED。 (我猜这也会导致 WAL 开销)
    • 然后重命名表。

你们能给我一些关于如何实现这一目标的指示吗?

Postgres 版本:9.5

最佳答案

我总觉得像这样的问题把几个不同的想法混为一谈,这让它们看起来比它们应该的更复杂。最小的性能影响是什么意思?生成大量 WAL 可能会增加文件 i/o 和 cpu 以及网络使用,但在大多数情况下不会对系统产生足够大的影响以产生面向客户端的影响。如果没有停机时间是最重要的事情,您应该专注于为此进行优化,而不用担心到达那里的过程是什么(在合理范围内)。

就是说,如果我站在你的立场上,我会首先使用表继承为数据设置分区,以便将来可以更轻松地对数据进行分段和处理。 (这不是完全必要的,但可能会让你将来的生活更轻松)。之后,我会编写一个脚本来慢慢浏览旧数据并使用“清空”数据创建新分区,交替创建分区、删除数据以及对主表进行清理。一旦自动化,您可以让它慢慢地或在下类时间搅拌直到完成。移动所有数据后,您可能需要对父级进行最终重新打包或完全真空处理,但即使没有它也可能没问题。同样,这不是最简单的想法,可能不是最快的方法(如果您可能有停机时间),但最终,您将拥有所需的模式,而不会导致任何服务中断。

关于sql - 如何存档一个巨大的 postgres 表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57253951/

相关文章:

mysql - 这些行运行时如何将时刻保存为时间戳?

mysql - 如何比较两列的重复值?

sql - 在 postgres 表中跨所有唯一阈值运行 "distinct on"

node.js - 使用 Postgresql 时如何在 SequelizeJS 模型中添加不区分大小写的唯一约束?

sql - 对于 pg_trgm,PostgreSQL GIN 索引比 GIST 慢?

sql: 按不同部分计算 um_no 的数量,按小时累计

mysql - 数据透视查询显示错误结果

regex - Postgres 的正则表达式

java - 使用 Commons Configuration 在数据库中存储属性

sql - 尝试按日期过滤 SQL 结果