mysql如何避免全表扫描_mysql查询触发全表扫描分析


EXPLAIN 显示 type=ALL 需警惕,表示全表扫描;主因是索引失效,如函数操作、隐式转换、前导通配符等,而非数据量大。

mysql如何避免全表扫描_mysql查询触发全表扫描分析

为什么 EXPLAIN 显示 type=ALL 就得警惕

这代表 MySQL 正在对整张表逐行检查,哪怕只查 1 条数据。常见诱因不是数据量大,而是查询条件没走索引——比如对字段用了函数、隐式类型转换,或 WHERE 里写了 IS NULL 却没对应索引。

  • EXPLAIN SELECT ...key 列是否为 NULL,是就说明没命中索引
  • possible_keys 有值但 keyNULL,大概率是索引失效,不是没建索引
  • 注意 Extra 列出现 Using filesortUsing temporary,往往伴随全表扫描,别只盯 type

哪些写法会悄悄让索引失效

不是加了索引就万事大吉。MySQL 对索引的使用很“死板”,稍不注意,优化器就放弃走索引。

  • WHERE name LIKE '%abc':前导通配符直接废掉 B+ 树的有序性
  • WHERE DATE(create_time) = '2024-01-01':对列用函数,索引无法比较
  • WHERE user_id = '123'user_idINT):字符串和数字比较触发隐式转换,索引失效
  • WHERE status != 1:范围不等于操作通常不走索引,尤其当 status 区分度低时

复合索引怎么建才真正生效

顺序决定一切。MySQL 只能按最左前缀匹配,且范围查询(>BETWEENLIKE 'abc%')后面的字段不再用于索引查找。

  • 查询是 WHERE a = 1 AND b > 10 AND c = 5,索引应建为 (a, b, c),不是 (a, c, b)
  • ORDER BY a DESC, b ASC 在 8.0+ 支持混合排序方向,但老版本只认统一方向,否则可能退化为文件排序
  • 避免冗余索引:(a)(a, b) 同时存在时,前者基本无用,还拖慢写入

小表要不要加索引、大表加索引卡住怎么办

“小表不用索引”是典型误解。只要查询频繁、有筛选条件,哪怕几千行也值得加索引;而大表加索引失败,往往卡在元数据锁或磁盘 I/O。

  • 加索引前先确认没有长事务:SELECT * FROM information_schema.INNODB_TRX 查阻塞源
  • 线上大表推荐用 ALGORITHM=INPLACE(5.6+),但注意它仍需排他 MDL 锁,DDL 期间不能改表结构
  • 如果 ALTER TABLE 卡住超 30 秒,优先查 SHOW PROCESSLIST 里有没有 Waiting for table metadata lock

索引不是越多越好,但漏掉一个关键查询路径,就可能让某条慢查稳居 QPS 前三。最麻烦的永远不是“没加索引”,而是“加了但没被用上”。