【问题标题】:Can I run a PostgreSQL Vacuum Once every 1-2 minutes?我可以每 1-2 分钟运行一次 PostgreSQL Vacuum 吗?
【发布时间】:2012-03-30 09:19:57
【问题描述】:

我正在为即将到来的项目考虑各种支持 MVCC 的数据库,而 PostgreSQL 引起了我的注意。

我的程序的需求大概是这样的:

  1. 从当前版本的数据库中读取一些信息,修改 80-90% 的数据并在一个或多个事务中将其写回(想象一下更新 Conway 的生命游戏中的网格,其中旧的并且需要新的网格状态)。

  2. 提交后等待 1-2 分钟。在此期间,客户端可以针对新数据发出读取。

  3. 重复。

数据库将被限制为 2-4GB。

~90% 的更改是对现有对象的更新,~5% 将是新对象,~5% 将是删除对象。

所以我的问题是,我是否可以合理地每 1-2 分钟运行一次简单的 VACUUM 命令作为步骤 1.5,并让 PostgreSQL 能够跟上每次可能进行的 2-3+GB 的更改?

【问题讨论】:

  • 您可能不需要手动运行它。调整该特定表的自动真空设置就足够了。但是只有在删除或插入大量行时才真正需要真空。更新不需要如此激进的真空。
  • 我的理解是每次更新都会生成一个带有新 XID 的新记录,并且由于每个周期我会更新 80-90% 的对象,我希望有很多“旧”记录清理。
  • 可能还需要注意的是,在第 1 步运行时,客户端也可能会从第“0”步对数据库的“旧”状态发出读取,因此这些旧记录需要在生成新的时可用。
  • @MindJuice:你说得对,更新会留下死元组。但是 Postgres 可以通过 HOT ("heap-only Tuple") updates 重复使用该空间而无需清理。一些例外情况适用 - 特别是如果索引列在更新中发生更改。换个说法,出于好奇:您还想到了哪些其他 MVCC 数据库?
  • 由于您在每次传递中都进行大量更新,因此可能值得使用稀疏的 fillfactor 创建表,以便在每个堆页面中为 HOT 更新留出足够的空间。跨度>

标签: performance postgresql vacuum mvcc


【解决方案1】:

我相信 Postgres 在这种情况下应该做得很好。这种情况并不常见,因此在大量更新之间手动清理似乎是一个合理的选择。

考虑您是否可以这样做,而不是进行大量更新,而是生成一组新表,分析它们(必要!),然后借助事务性 ddl 的力量,删除旧表并重命名新表进入他们的位置。这应该可以减轻您对 VACUUM 的担忧。

在这种情况下,您应该进行一些认真的调整。特别是,查看 shared_buffers、检查点相关参数和真空相关参数。另外,请记住使用实际工作负载进行基准测试。

【讨论】:

  • 关于使用两个单独的表并在最后重命名的有趣建议。那可能对我有用。我会考虑一下。谢谢!
  • 要重命名表,数据库首先要锁定表。这比更新的普通行锁要慢得多。
  • @FrankHeikens:这是一个权衡,OP 想要更新几乎整个表,一个简短的独占锁很容易比处理 VACUUM 和其他东西更好。如果读者只发出简短的查询,则尤其如此。或者,可以想象在客户端执行此操作 - 一个小的 search_path 舞蹈可能意味着“旧”读者使用旧模式中的表,新读者​​使用新模式中的表,而在后台您正在准备另一个版本。然后你删除不再被任何人使用的模式。
  • 如果您在每个周期都将插入到新表中,请确保有一个事务将使用中的表重命名为“旧”名称并将新表重命名为表-正在使用。在此事务的提交和删除旧表之间留出一些时间,因为在提交后使用旧表的 OID 计划的事务可能仍在执行的一小段时间。您可能希望使用“旧”表名的 DROP TABLE IF EXISTS 语句启动“将新事务移动到位”事务。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-23
  • 1970-01-01
  • 1970-01-01
  • 2012-08-26
  • 2013-03-23
  • 2018-09-30
相关资源
最近更新 更多