避免全表扫描的关键是合理使用索引:为高频查询和连接字段建索引,遵循最左前缀原则,且不在索引列上使用函数或表达式。

避免全表扫描是MySQL查询优化的关键一步,核心在于让查询能有效利用索引,减少不必要的数据读取。
确保查询条件字段有合适索引
全表扫描往往是因为WHERE、JOIN、ORDER BY或GROUP BY中使用的字段缺少索引。不是所有字段都适合建索引,重点覆盖高频查询条件和连接字段。
- 对WHERE子句中频繁出现的列(如user_id、status、create_time)建立单列或联合索引
- 联合索引注意最左前缀原则:查询包含索引最左侧连续列时才能命中,例如索引(a, b, c),可命中a、a,b、a,b,c,但无法命中b或b,c
- 避免在索引列上使用函数或表达式,如WHERE YEAR(create_time) = 2024会跳过索引,应改写为WHERE create_time >= '2024-01-01' AND create_time
检查执行计划,确认是否走索引
用EXPLAIN分析SQL,重点关注type、key、rows和Extra字段。
- type值为ALL表示全表扫描;理想是const、ref、range或index
- key显示实际使用的索引名,为空说明未走索引
- rows越小越好,代表预估扫描行数;若远大于结果集数量,说明索引选择不佳或存在隐式类型转换
- Extra中出现Using filesort或Using temporary虽不等于全表扫描,但常伴随性能问题,需结合索引优化
避免导致索引失效的常见写法
即使有索引,某些SQL写法也会让优化器放弃使用它。
- 使用!=或(非等值判断通常无法高效利用B+树索引)
- 对索引列使用LIKE且以通配符开头,如name LIKE '%abc';可改为name LIKE 'abc%'并配合前缀索引
- 索引列参与运算或类型隐式转换,如WHERE mobile = 13812345678(mobile是VARCHAR),MySQL会将整数转为字符串比对,可能使索引失效
- OR连接多个条件时,只有所有分支字段都有索引才可能走索引;否则建议拆成UNION或改用IN
合理设计索引,不过度依赖单列索引
单列索引堆砌容易引发索引冗余,而联合索引设计不当又会导致覆盖不足。
- 优先考虑高频组合查询场景,把过滤性最强的列放在联合索引最左侧
- 利用覆盖索引减少回表:SELECT只查索引列时,可直接从索引获取全部数据,避免访问聚簇索引(主键索引)
- 对大文本或长字符串字段,考虑前缀索引(如INDEX idx_title (title(50))),平衡索引大小与区分度
- 定期用SHOW INDEX FROM table_name和慢查询日志分析索引使用率,删除长期未被命中的冗余索引










