为了支持高并行性,PostgreSQL 使用多版本并发控制 (MVCC) 存储行。但是,MVCC对更新查询有一些缺点。具体来说,更新需要向表中添加新版本的行。这还可能需要为每个更新的行添加新的索引项,并且删除旧版本的行及其索引项可能很昂贵。
为了帮助减少更新的开销,PostgreSQL 有一种针对堆中仅有元组 (HOT) 的优化。以下情况下可以进行此优化
更新不会修改表索引(不包括摘要索引)引用的任何列。在核心PostgreSQL 发行版中,唯一的汇总索引方法是BRIN。
包含旧行的页面上有足够的空闲空间可用于更新后的行。
在这种情况下,仅堆元组提供了两种优化
无需新的索引项表示更新的行,但摘要索引可能仍需要更新。
当某行被多次更新时,除了最旧和最新的行版本,其他行版本可在序号操作过程中完全删除,例如 SELECT
,而不必定期进行回收操作。(索引始终引用原始行版本的 页面项标识符。与该行版本关联的元组数据会删除,其项标识符会转换成重定向,指向仍可能对某些并发事务可见的最旧版本。不再对任何人可见的中间行版本会完全删除,而关联的页面项标识符将可供重用。)
降低表 fillfactor
,可以提高页面空间为HOT更新提供足够的空间。如果不这么做,HOT更新仍会因为新行会自然迁移到新页面和为新行版本留有足够可用空间的现有页面而发生。系统视图 pg_stat_all_tables 允许监控 HOT 更新和非 HOT 更新的出现情况。