PostgreSQL查询计划未显示Table2堆访问的原因咨询
这是个很棒的问题!你观察到的现象其实是PostgreSQL几个核心特性共同作用的结果,我来一步步拆解给你看:
1. 二级索引自动包含主键列
PostgreSQL的所有二级索引都会自动附加表的主键列作为行定位器——因为你的Table2主键是id,所以你创建的ix_Table2_groupby_orderby索引实际包含的列是:groupby, orderby, id。这是PostgreSQL的默认行为,原本是为了让索引条目能快速定位到堆中的对应行,但这里它刚好帮了我们另一个大忙。
2. 查询所需列可通过索引列推导
看你填充Table2的脚本,查询中需要的其余列都能通过索引已有的列直接计算得出:
local_search=orderby % 50:索引里有orderby字段,直接计算即可global_search=id % 1000:索引里包含主键id,直接取模就能得到padding=RPAD('Value ' || id || ' ', 100, '*'):用索引里的id就能生成这个填充字符串
PostgreSQL的查询优化器能识别出这些计算逻辑,直接在索引扫描阶段就完成所有列的计算,完全不需要去访问堆里的实际数据行。
3. 可见性映射(VM)让索引-only扫描成为可能
因为你的表是刚创建并批量插入数据的,还没有发生过任何删除或更新操作,PostgreSQL的可见性映射(Visibility Map)会标记这些数据页面为"全可见"。这意味着PostgreSQL可以安全地使用索引-only扫描——不需要访问堆来检查行的可见性(所有行对当前事务都是可见的)。这就是为什么EXPLAIN ANALYZE和EXPLAIN VERBOSE都看不到堆访问记录的原因。
如果之后你对Table2执行了更新/删除操作,且没有运行VACUUM来更新可见性映射,那么查询可能就需要访问堆来确认行的可见性了。
内容的提问来源于stack exchange,提问作者Radim Bača
相关产品推荐
相关产品推荐

