type字段最该盯住,因为它直接决定mysql访问数据方式、是否走索引、扫描行数及是否需临时表或排序,是性能分水岭;all和range间可能相差90ms。

type字段为什么是执行计划里最该盯住的指标
因为type直接反映MySQL访问数据的方式,决定了查询是否走索引、扫描多少行、是否需要临时表或排序。它不是“参考项”,而是性能分水岭——ALL和range之间,可能就是100ms和10ms的差距。
看到ALL或index时必须立刻检查的三件事
ALL(全表扫描)和index(全索引扫描)本质都是遍历,只是后者走的是B+树叶子节点。它们常被误认为“用了索引”,实则毫无选择性。
- 确认WHERE条件列是否真的有索引:比如
WHERE status = ? AND created_at > ?,但只在status上建了单列索引,created_at没覆盖,优化器大概率弃用该索引,退化为ALL - 检查隐式类型转换:
WHERE mobile = 13812345678(mobile是VARCHAR),会触发全表扫描,因为数字字面量被转成字符串时无法利用索引;应写成WHERE mobile = '13812345678' - 验证参数是否为NULL或空字符串:
WHERE name != ''或WHERE name IS NOT NULL通常无法走索引,尤其当该列NULL值占比高时,优化器宁可选ALL
ref和range之间的取舍不只看type本身
ref表示等值匹配非唯一索引,range表示范围扫描(BETWEEN、IN、>=等)。表面看ref更优,但实际要结合rows和Extra判断:
- 如果
type=ref但rows=50000,而type=range且rows=200,后者更高效 -
range搭配Using index condition(ICP)是健康信号;若出现Using where,说明过滤下推失败,可能因函数包裹列(如WHERE YEAR(created_at) = 2024) -
IN列表超过几百项时,type仍标range,但实际性能接近ALL,应拆成批量ID查询或改用临时表
eq_ref和const被误判时的典型陷阱
const意味着单行查找(主键/唯一索引等值),eq_ref多见于JOIN中主键关联。但它们容易被“假象”误导:
-
SELECT * FROM user WHERE id = ?显示const,但如果id字段是VARCHAR且传入数字参数,仍可能因隐式转换失效 - LEFT JOIN中右表出现
eq_ref,不代表一定高效——若右表关联条件未走索引,实际是驱动左表后对右表逐行全扫,rows乘积会爆炸 - 子查询返回单行时标记
const,但若子查询本身慢(比如含ORDER BY + LIMIT 1无索引),整体仍是瓶颈
真正可靠的判断依据永远是rows×实际执行时间,而不是type的“好听名字”。一个标着ref却扫10万行的查询,比标range但只扫200行的更危险。











