内容提要
本文讨论了PostgreSQL中的可见性图和仅索引扫描的连接,介绍了可见性图的作用和维护方式,并通过示例演示了其工作原理。还讨论了数据修改对可见性图的影响以及VACUUM在更新可见性图方面的优化。最后,介绍了使用pg_visibility扩展查看可见性图的方法。
延伸解读
仅索引扫描的性能关键:可见性图
可见性图是仅索引扫描高效执行的基础。当页面的all-visible标志置位时,PostgreSQL可跳过回表检查可见性,从而减少堆抓取。若可见性图未及时更新,即使执行计划显示Index Only Scan,仍可能产生大量Heap Fetches,导致性能下降。因此,定期VACUUM以维护可见性图对优化查询性能至关重要。
数据修改对可见性图的影响
任何数据修改都会重置相关页面的all-visible标志。例如,更新一行会同时影响旧版本所在页和新版本所在页,使这些页面不再all-visible。后续查询需要回表检查这些页面中的元组可见性,增加Heap Fetches。这解释了为何频繁更新的表可能难以享受仅索引扫描带来的性能优势。
VACUUM的优化与可见性图更新
从PostgreSQL v14起,VACUUM引入了一项优化:当表中含有死元组的页面比例不超过2%时,会跳过索引清理。这可能导致某些页面无法被标记为all-visible,因为指向死元组的索引项未被移除。若需强制VACUUM清理索引,可使用VACUUM (INDEX_CLEANUP ON)或设置表级参数vacuum_index_cleanup = on。
使用pg_visibility扩展验证可见性图
pg_visibility扩展允许直接查看可见性图的内容。通过查询pg_visibility_map函数,可以获取每个页面的all-visible和all_frozen标志状态。这有助于验证VACUUM是否按预期更新了可见性图,以及诊断仅索引扫描效率低下的原因。例如,在示例中,更新一行后,只有两个页面的all-visible标志被重置,与理论分析一致。
Q&A
PostgreSQL中的可见性图是什么?
可见性图是PostgreSQL中用于存储每个8kB页面的两个标志:all-frozen和all-visible,帮助优化索引仅扫描。
VACUUM操作如何影响可见性图?
VACUUM操作会移除死元组并维护可见性图,定期执行VACUUM可以提高索引仅扫描的效率。
如何使用pg_visibility扩展查看可见性图?
可以通过创建pg_visibility扩展并使用SELECT语句查询可见性图,查看页面的可见性状态。
数据修改如何影响可见性图的all-visible标志?
数据修改会重置相应页面的all-visible标志,导致索引仅扫描的效率下降。
PostgreSQL v14中的VACUUM优化有什么影响?
PostgreSQL v14中的VACUUM优化可能导致在某些情况下跳过不必要的索引清理,从而影响可见性图的更新。
如何强制VACUUM清理索引以提高效率?
可以通过设置VACUUM的INDEX_CLEANUP选项为TRUE,强制VACUUM清理索引,从而提高索引仅扫描的效率。