1. EXPLAIN 怎么用?关键字段怎么读?

EXPLAIN SELECT ... 查看执行计划。关键列:

🎯 面试要点

  • type 达到 range/ref 一般可接受,ALL 且 rows 大要处理
  • EXPLAIN ANALYZE(8.0)能给出实际执行时间和行数,更准确
  • 避免 filesort:ORDER BY 与索引列顺序一致;避免临时表:GROUP BY 用索引

2. 线上慢 SQL 如何排查和优化?(完整流程)

  1. 开启慢查询日志:long_query_time=1(超过 1 秒记录);SHOW VARIABLES LIKE 'slow_query_log' 确认
  2. 分析工具:mysqldumpslow 汇总慢日志(按耗时/次数排序),或 pt-query-digest 更专业
  3. EXPLAIN 定位问题:type=ALL?没走索引?filesort?临时表?
  4. 对症优化:
    • 缺索引 → 补索引(先看 where/order/join 列)
    • 索引失效 → 改写 SQL(去掉函数/隐式转换)
    • 大字段回表 → 覆盖索引 / 少 select *
    • 数据量太大 → 归档、分页改造、分库分表
    • 锁等待 → 看是否长事务、行锁升级表锁
  5. 验证:优化后 EXPLAIN rows 明显下降、执行时间达标

🎯 面试要点

  • 慢 SQL 处理优先级:先看是否没走索引,再看是否需要重构 SQL,最后才考虑分表
  • 监控:SHOW PROCESSLIST 看当前执行的 SQL(谁在跑、跑了多久)
  • 避免在 where 中做大量计算——把计算放应用层或加冗余字段

3. 深分页为什么慢?怎么优化?

LIMIT 100000, 20 慢的原因:MySQL 要扫描并丢弃前 100000 行(只能一条条跳过,无法直接定位)。数据越大越慢。

优化方案:

  1. 游标分页(推荐):WHERE id > 上一页最后一条的 id ORDER BY id LIMIT 20——直接走索引定位
  2. 延迟关联:先用覆盖索引查出 id 再回表取行: SELECT * FROM t JOIN (SELECT id FROM t ORDER BY id LIMIT 100000, 20) tmp ON t.id = tmp.id
  3. 禁止"跳页"的场景(用户只能翻下一页)适合游标;必须跳页则延迟关联

🎯 面试要点

  • 游标分页需要排序字段唯一稳定(id 天然满足)
  • ORDER BY 非索引列 + LIMIT 大偏移 = 双倍慢(filesort + 跳过)
  • 大数据量表的分页尽量让产品限制深度(如最多 100 页)

4. 日常 SQL 优化的好习惯?

🎯 面试要点

  • 优化大方向:少访问(索引)→ 少回表(覆盖)→ 少传输(精简列)→ 少排序(索引排序)
  • 不要过度优化:QPS 低、数据量小的 SQL 不值得加索引

🎤 常见面试追问

  1. EXPLAIN 的 type 列怎么判断好坏?——性能从好到差:system > const > eq_ref > ref > range > index > ALL。出现 ALL(全表扫)且 rows 大就要优化。
  2. 深分页为什么慢?怎么优化?——LIMIT 100000,20 要扫描并丢弃前 10 万行。优化:游标分页(WHERE id > 上页最大 id)或延迟关联(先查 id 再回表)。
  3. Using filesort 是什么意思?怎么消除?——排序没走索引(文件排序)。消除:让 ORDER BY 列与索引顺序一致,或加覆盖索引。
  4. 慢 SQL 排查的完整流程?——开慢查询日志(long_query_time=1)→ mysqldumpslow 汇总 → EXPLAIN 定位(type=ALL? 没走索引? filesort?)→ 对症(补索引/改写 SQL/覆盖索引)→ 验证 rows 下降。
  5. select * 为什么不好?——多回表(二级索引覆盖不了大字段)、多传输、多解析。只取需要的列。

📖 名词解释(本页术语)

术语 大白话解释
EXPLAIN查看 SQL 执行计划的命令(怎么查、扫多少行、用没用索引)——SQL 优化的第一步。
type(访问类型)EXPLAIN 里的关键列,表示访问方式:const/ref/range 好,index/ALL 差。
rows预估扫描行数,越小越好(优化前后对比用它验证)。
Using filesortExtra 提示:排序没走索引,用了文件排序(数据量大时慢)。
Using temporary用临时表(GROUP BY/DISTINCT 常见),要优化。
慢查询日志记录超过 long_query_time 的 SQL 的日志文件,排查慢 SQL 的第一手资料。
游标分页WHERE id > 上一页最后一条 id 的分页方式,直接走索引,深分页不慢。
延迟关联先用覆盖索引查出 id 集合,再 join 回原表取整行——减少深分页的回表。
隐式类型转换varchar 列用数字查(WHERE phone = 13800000000)——MySQL 隐式 CAST 导致索引失效。
⚠️ 本页面由 AI 生成,内容仅供参考,请以官方文档和实际源码为准。