EXPLAIN显示type=ALL却未走索引,主因是隐式类型转换或函数包裹导致索引失效;如WHERE id='123'(id为INT)或WHERE DATE(create_time)='2024-01-01',均使索引无法使用。

为什么 EXPLAIN 显示 type=ALL 却没走索引
这通常不是索引没建,而是查询写法触发了隐式类型转换或函数包裹,导致索引失效。比如 WHERE id = '123'(id 是 INT),MySQL 会把字符串转成数字再比对,但优化器可能放弃索引;更常见的是 WHERE DATE(create_time) = '2024-01-01'——DATE() 函数让 create_time 索引完全失效。
实操建议:
- 用
SHOW WARNINGS查看优化器重写后的语句,确认是否被改写成不可索引的形式 - 避免在索引列上使用函数、表达式、
LIKE '%xxx'开头的模糊匹配 - 字符串比较时确保类型一致:
WHERE status = 1(status是TINYINT),别写成'1' - 时间范围查询优先用
BETWEEN或闭区间:WHERE create_time >= '2024-01-01' AND create_time ,而非DATE(create_time) = ...
EXPLAIN FORMAT=JSON 比传统 EXPLAIN 多看出什么
传统 EXPLAIN 只给粗粒度信息,比如 key 用了哪个索引、rows 预估扫描行数;而 FORMAT=JSON 能暴露优化器真实决策路径,特别是是否发生索引合并(index_merge)、是否使用了索引条件下推(ICP)、是否因 ORDER BY 需要临时文件排序等。
关键字段注意:
-
attached_condition:显示下推到存储引擎层的过滤条件,ICP 生效时这里会变短 -
using_index:为True表示覆盖索引,无需回表 -
using_filesort或using_temporary:说明排序/分组没走索引,性能瓶颈大概率在这 -
filtered值过低(如10.00)说明虽然走了索引,但索引选择性差,大量无效行被拉到 server 层过滤
哪些 ORDER BY 场景必须重写才能走索引
只有当 ORDER BY 字段顺序与索引最左前缀严格一致、且无混合 ASC/DESC 时,才可能利用索引排序。例如有联合索引 (a, b, c),则 ORDER BY a, b 可走索引,但 ORDER BY b, c 不行;ORDER BY a DESC, b ASC 在 MySQL 8.0 之前也基本失效。
系统功能强大、操作便捷并具有高度延续开发的内容与知识管理系统,并可集合系统强大的新闻、产品、下载、人才、留言、搜索引擎优化、等功能模块,为企业部门提供一个简单、易用、开放、可扩展的企业信息门户平台或电子商务运行平台。开发人员为脆弱页面专门设计了防刷新系统,自动阻止恶意访问和攻击;安全检查应用于每一处代码中,每个提交到系统查询语句中的变量都经过过滤,可自动屏蔽恶意攻击代码,从而全面防止SQL注入攻击
常见可重写方式:
- 把
ORDER BY RAND()改为应用层随机取 ID 后查,或用OFFSET+LIMIT分页模拟(但大数据量仍慢) -
ORDER BY func(x)(如UPPER(name))无法走索引,考虑加函数索引(MySQL 8.0+):CREATE INDEX idx_name_upper ON t ((UPPER(name))) - 多表
JOIN后ORDER BY非驱动表字段,往往触发using_filesort,优先调整JOIN顺序或加覆盖索引包含排序字段
查询重写时容易忽略的统计信息偏差问题
即使重写后语法“看起来能走索引”,如果表的统计信息陈旧(比如刚批量导入百万数据但没 ANALYZE TABLE),优化器仍可能基于错误的行数估算选择全表扫描。尤其在 WHERE 条件区分度高但优化器误判为低时,EXPLAIN 会显示 type=range 却实际扫描巨量行。
验证和修复步骤:
- 查统计信息更新时间:
SELECT UPDATE_TIME FROM information_schema.tables WHERE TABLE_SCHEMA = 'db' AND TABLE_NAME = 't' - 强制刷新:
ANALYZE TABLE t(线上慎用,会锁表;MySQL 5.7+ 可设innodb_stats_auto_recalc = ON) - 必要时用
FORCE INDEX临时绕过错误选择,但只是兜底,不能替代根本优化 - 注意
innodb_stats_persistent是否开启,关闭时重启后统计信息丢失,可能导致计划突变
真正难的不是写出能走索引的 SQL,而是理解优化器在特定数据分布、统计精度、版本特性下的真实行为边界。一次 EXPLAIN 看不出问题,得结合 FORMAT=JSON、执行时间、SHOW PROFILE 和实际 slow log 对齐才可靠。









