explain中type=all即确定发生全表扫描,关键信号还包括key=null、rows接近总行数、extra含using where但无using index;常见原因有函数操作、隐式转换、前导通配符、or条件失衡及优化器成本误判。

直接看 EXPLAIN 输出里的 type 字段,只要它是 ALL,基本就是全表扫描——不是“可能”,是确定没走索引。
怎么快速揪出正在全表扫描的 SQL?
别等慢查询日志积累半天。先连上生产库,用 SHOW PROCESSLIST 看当前活跃会话里哪些在扫大表:
-
State是Sending data且Time超过几秒,大概率在扫; -
Info字段里带SELECT+ 大量WHERE条件但没ORDER BY或LIMIT,尤其注意有没有函数调用(比如DATE(created_at)); - 配合
INFORMATION_SCHEMA.PROCESSLIST查更全:SELECT ID, INFO, TIME FROM INFORMATION_SCHEMA.PROCESSLIST WHERE COMMAND = 'Query' AND TIME > 3 AND INFO LIKE '%SELECT%';
EXPLAIN 里哪些信号说明它在全表扫描?
EXPLAIN 不是看热闹,重点盯三个字段:
-
type是ALL:铁证,没走任何索引; -
key是NULL:即使possible_keys有值,key为空也等于没用; -
rows数字极大(比如 >50000):哪怕type是index,扫整张索引树也等价于全表扫描; -
Extra出现Using where但没Using index:说明查了索引还得回表,如果rows很大,实际开销接近全表。
为什么明明建了索引还全表扫描?常见失效场景
索引存在 ≠ 被用。这几个写法会让 MySQL 直接放弃索引:
- WHERE 中对字段用了函数:
WHERE YEAR(create_time) = 2026→ 改成WHERE create_time >= '2026-01-01' AND create_time ; - 隐式类型转换:
WHERE user_id = '123'(user_id是 INT)→ 字符串强制转数字,索引失效; - LIKE 左模糊:
WHERE name LIKE '%abc'→ 没法走 B+ 树前缀匹配; - 联合索引顺序错:
INDEX(a,b,c),但查询只用WHERE c = 1→ 不满足最左前缀,直接跳过。
线上不敢随便改 SQL?先加索引试试
如果确认是缺失索引导致的 ALL,加索引比重写业务逻辑快得多,但要注意:
- 优先覆盖
WHERE条件字段,再追加ORDER BY和SELECT字段(做成覆盖索引); - 避免单列索引堆砌,比如
WHERE a=1 AND b=2,建INDEX(a,b)比分别建两个好; - 加索引前用
pt-online-schema-change或 MySQL 8.0+ 的ALGORITHM=INSTANT,别锁表; - 加完立刻
EXPLAIN验证,别信“应该能走”。
全表扫描本身不致命,致命的是它出现在高频接口或大表上。真正麻烦的是那些 rows 显示几千、但实际执行扫了百万行的 SQL——EXPLAIN 的预估不准时,得靠 SHOW PROFILE 或性能模式(performance_schema)看真实 I/O 开销。











