为了支持高并发,PostgreSQL 使用 多版本并发控制 (MVCC)来存储行。然而, MVCC 对更新查询有一些缺点。 具体来说,更新要求把行的新版本加入表中。 这还可能要求为每个被更新的行增加新的索引条目,而删除行的旧版本及其 索引条目的代价可能很高。
为了帮助降低更新开销, PostgreSQL 提供了一种称为 heap-only tuples(HOT,堆内元组)的优化。这种 优化在以下条件下是可能的:
更新没有修改表的索引所引用的任何列(汇总索引除外)。 核心 PostgreSQL 发行版中唯一的汇总索引 方法是 BRIN。
包含旧行的页面有足够的空闲空间容纳更新后的行。
在这种情况下,堆内元组提供两项优化:
表示被更新行不需要新的索引条目,不过汇总索引可能仍需要更新。
当一行被更新多次时,除了最旧和最新版本之外的行版本可以在正常操作
期间(包括 SELECT)被完全移除,而不需要周期性的
清理操作。(索引始终引用原始行版本的
页面条目标识符。
与该行版本关联的元组数据被移除,其条目标识符被转换为一个重定向,
指向可能仍对某些并发事务可见的最旧版本。
对任何人都不再可见的中间行版本被完全移除,相关的页面条目标识符
被释放以便重用。)
您可以通过减小表的 fillfactor
来提高页面拥有足够空间进行 HOT 更新的可能性。
即使不这样做,HOT 更新仍然会发生,因为新行会自然
地迁移到新页面以及有足够空闲空间容纳新行版本的现有页面。
系统视图 pg_stat_all_tables
可以用于监控 HOT 更新和非 HOT 更新的发生情况。