SQL 明明建了索引,执行计划却还是全表扫描,多数不是索引坏了,而是查询写法让优化器用不上。按下面五个场景逐一排查。
一、列上套了函数或运算:where date_trunc('day', created_at) = ... 会让普通 B-tree 索引失效,改成范围条件或建表达式索引,两者选其一,别两个都不做。
二、隐式类型转换:varchar 列传数字、int 列传字符串,优化器会悄悄加 cast,索引直接作废。先看执行计划里有没有 Filter 而不是 Index Cond,再核对参数类型。
三、OR 条件跨列:where a = 1 or b = 2 时单列索引很难全用上,改写成 UNION 或建多列索引要看选择性,数据分布不均时效果差异很大。
四、统计信息过期:表刚批量导入或删除大量数据后,优化器对行数估计失真,会误判全表更快。先 ANALYZE 再看计划,别急着加索引。
五、LIKE 前缀通配:'%abc' 天然走不了 B-tree,'abc%' 才可以。确实要模糊搜索就评估 trigram 索引,别指望普通索引解决所有 LIKE。
排查顺序建议:先 EXPLAIN ANALYZE 看实际耗时和 Rows Removed by Filter,再对症改写,最后才考虑加索引。索引不是越多越好,写放大和维护成本也要算进去。
大家还遇到过哪些索引失效的坑?是类型转换、函数,还是统计信息问题最常见?