MySQL 索引失效与 EXPLAIN 查询计划
MySQL 索引失效与 EXPLAIN 查询计划
“我建了索引,查询为什么还是慢?”索引是否被使用取决于查询条件、数据分布和优化器估算。判断问题时,不应只背“索引失效清单”,而要看执行计划,并用代表性数据验证。
1. 准备一个示例
1 | |
联合索引按列顺序组织。(user_id, status, created_at) 一般可用于从最左列开始的前缀条件,例如只按 user_id 查,或按 user_id 和 status 查。跳过最左列后,不能简单认为后续列仍可像独立索引一样定位。
2. 先用 EXPLAIN 看计划
1 | |
重点观察访问类型、候选索引、实际选择的 key、估算扫描行数和额外排序信息。字段含义会随输出格式和 MySQL 版本有所不同;EXPLAIN FORMAT=TREE 可呈现树形计划,MySQL 支持时还可用 EXPLAIN ANALYZE 对查询进行实际执行并显示迭代器统计。后者会运行查询,应在适当环境和数据范围内使用。
3. 常见的索引使用问题
跳过联合索引的最左列
索引是 (user_id, status, created_at),只按 status 查询时,通常不能利用该索引快速定位到一段连续范围。应根据真实查询模式设计索引,而不是机械地把所有列放在一个联合索引中。
对索引列做表达式计算
1 | |
可改为范围条件:
1 | |
隐式类型转换或不匹配的比较方式
比较的列类型和参数类型不一致时,转换方式可能影响索引使用。应让参数类型与列定义匹配,并检查字符集、排序规则和实际计划。
低选择性和成本估算
某列只有少数几种值时,索引可能筛不掉多少记录;优化器可能判断扫描表更便宜。索引存在不代表每次都会被选中,也不代表选中后一定更快。
4. 一个可靠的分析流程
- 用具有代表性的数据和参数重现慢查询。
- 看
EXPLAIN的访问路径和估算行数。 - 检查索引列顺序、过滤条件、排序和返回列。
- 必要时使用实际执行计划或慢查询信息核实估算。
- 调整 SQL 或索引后,在相同数据规模下比较结果。
- 评估写入成本、索引空间和其他查询的影响。
不要为了让某个查询显示“用上索引”而盲目添加索引;索引会增加写入和存储成本。计划是解释优化器的选择,最终仍要结合真实负载测量。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 GuMing的殿堂!
评论

