创建rating列索引未降低查询执行成本,求原因分析
为什么你的rating索引没降低查询成本?
这事儿我碰到过好几次,核心原因其实是你的索引根本没被查询用上,再加上数据量太小,优化器直接选了全表扫描。具体拆成几点说:
1. 普通索引不支持带表达式的条件匹配
你建的应该是rating列的普通B-tree索引吧?但你的查询条件是rating*3 > 20——PostgreSQL的普通索引只会存储rating的原始值,没办法直接匹配这个计算后的条件。虽然这个条件等价于rating > 20/3(约6.666),但优化器默认不会主动对带表达式的条件做反向推导去匹配索引,所以它还是会走全表扫描,成本自然没变化。
2. 数据量太小,全表扫描本来就更划算
你的表只有2680条元组,这个量级的数据全表扫描的开销极低——PostgreSQL的优化器会评估:走索引需要先遍历索引找到符合条件的行,再回表取出所有列,这个过程的开销可能比直接一次性扫完整个表还高。所以哪怕你建了合适的索引,优化器也可能选择全表扫描,成本数值自然不会变。
怎么解决?
有两个实用思路:
- 改写查询,匹配普通索引:把条件改成
WHERE rating > 20/3,这样优化器能直接用上rating列的普通索引(如果它觉得划算的话)。 - 建表达式索引:针对你查询里的计算式建索引,比如:
这样查询CREATE INDEX idx_cup_matches_rating_expr ON cup_matches ((rating * 3));WHERE rating*3 >20就能直接匹配这个索引了。
验证方法
你可以用EXPLAIN ANALYZE SELECT * from cup_matches WHERE rating*3 > 20;看看执行计划,里面如果显示Seq Scan(全表扫描),就说明索引没被用上;如果是Index Scan,才说明索引生效了。
内容的提问来源于stack exchange,提问作者M.A.G
相关产品推荐
相关产品推荐

