PostgreSQL 11.6未始终使用索引咨询:查询order_status=1走全表扫描
问题解答
没错,就是因为order_status = 1的行占比过高,PostgreSQL查询优化器判定全表扫描的执行成本比使用B-tree索引更低,所以选择了顺序扫描。
具体原因分析
数据占比计算
全表总行数为:197739 + 465879 + 59133 + 4883 = 727634,其中order_status = 1的行数占比约为64%,超过了表中一半以上的数据。索引与全表扫描的成本差异
- 使用B-tree索引时,需要先通过索引定位到目标行的物理位置,再执行回表操作读取完整行数据,这个过程涉及随机IO,当需要返回的行数过多时,随机IO的开销会急剧上升。
- 全表扫描是顺序读取所有数据,虽然会读取不需要的行,但顺序IO的效率远高于随机IO,对于占比极高的数据集,整体成本反而更低。
优化器的决策逻辑
PostgreSQL优化器会依赖表的统计信息(你给出的各状态行数统计就是核心依据)估算执行成本,当查询返回的行数占表总行数的比例超过阈值(通常经验值在10%-20%左右,具体取决于表结构、存储介质等),就会优先选择全表扫描。
验证方法
你可以通过以下方式验证这个结论:
- 执行
EXPLAIN ANALYZE select * from tbl_order where order_status = 1;,查看执行计划中的成本估算和实际执行耗时。 - 强制关闭全表扫描:
SET enable_seqscan = off;,再执行相同查询,对比强制走索引后的执行耗时,会发现全表扫描确实更快。
内容的提问来源于stack exchange,提问作者sffortytwo
相关产品推荐
相关产品推荐

