读执行计划时不要只盯着 type 或“是否走索引”。先确认访问对象和顺序,再看每步扫描多少、过滤多少、是否排序,最后用实际执行数据验证估算。
Table of contents
Open Table of contents
三种入口
EXPLAIN SELECT ...;
EXPLAIN FORMAT=TREE SELECT ...;
EXPLAIN ANALYZE SELECT ...;
普通 EXPLAIN 给出表格估算;FORMAT=TREE 更容易看懂算子父子关系;EXPLAIN ANALYZE 会真实执行并报告实际行数与耗时。对更新语句或昂贵查询使用最后一种前,先在安全环境评估副作用。
先读这些列
| 字段 | 要回答的问题 |
|---|---|
type | 如何访问:常量、范围、索引还是全表扫描 |
possible_keys | 理论上有哪些候选索引 |
key | 最终选择哪个索引 |
key_len | 实际用到索引键的多长前缀 |
rows | 优化器估计要检查多少行 |
filtered | 读取后预计保留百分比 |
Extra | 覆盖、条件下推、排序、临时表等补充信息 |
ALL 常代表全表扫描,但小表全扫可能最便宜;Using filesort 表示额外排序算法,不等于一定写磁盘;Using index 常表示覆盖读取,不代表用了“最优索引”。上下文比单个标签重要。
用估算与实际的差距找问题
运行索引实验脚本。如果估算 10 行、实际 10 万行,优化器可能缺少准确统计信息,或列之间高度相关。先更新统计信息、检查数据分布,再考虑改索引或 SQL。
调优前后记录相同条件下的执行计划、实际耗时、返回行数与数据规模。缓存冷热、并发和参数分布不同,单次执行时间不能证明优化有效。
下一步
继续阅读06-07 联合索引、覆盖索引与索引下推,学习把查询形状翻译为索引列顺序。