跳到正文
hello world

MySQL之EXPLAIN

一、B+Tree 与磁盘 I/O

  • B+Tree 每次向下查找一层,都会产生一次 磁盘 I/O
  • 树的高度越低,I/O 次数越少,查询越快

二、聚簇索引(Clustered Index)

InnoDB 中,主键索引就是聚簇索引

聚簇索引结构

id
 ↓
完整的一行数据
  • 叶子节点直接存储 整行数据
  • 一张表 只有一个 聚簇索引(通常是主键)

三、二级索引(Secondary Index)

  • 叶子节点存储的是:主键值,而非整行数据

回表(Bookmark Lookup)

二级索引 → 主键 id → 聚簇索引 → 整行数据
  • 使用二级索引查非索引列时,会发生 回表
  • 如果只查询 二级索引列 + 主键,则 不需要回表

覆盖索引(Covering Index)

  • 查询的列 全部包含在索引中
  • Extra 中显示:Using index
  • ✅ 性能最好,避免回表

四、EXPLAIN 解读

字段 含义 如何判断优劣
type 访问类型(查询方式) 越靠近 const 越好
ref:普通索引
range:索引范围扫描(如 BETWEEN>
❌ 避免 ALL(全表扫描)
key 实际使用的索引 不能为 NULL
rows 预估扫描行数 越小越好
Extra 额外信息 Using index(覆盖索引)
⚠️ Using filesort
⚠️ Using temporary

EXPLAIN 阅读顺序(口诀)

  1. type:有没有全表扫描
  2. key:是否真正用到索引
  3. rows:扫描了多少行
  4. Extra:是否有排序、临时表、覆盖索引

五、SQL 慢查询排查流程

SQL 很慢
   │
   ▼
① 有没有走索引?
   │
   ▼
② 为什么没走索引?
   │
   ▼
③ 扫描了多少行?
   │
   ▼
④ 有没有排序?
   │
   ▼
⑤ 有没有回表?

六、常见导致索引失效的原因

  • 隐式类型转换
  • 联合索引违反 最左匹配原则
  • 对索引列做函数操作
  • OR 条件不当
  • LIKE '%xxx'(前模糊)

七、ORDER BY 为什么会慢?

  • ORDER BY ageage 无索引
  • MySQL 无法利用索引排序
  • 结果:Using filesort
  • 本质:把数据查出来后再在内存 / 磁盘中排序

八、事务隔离级别与 MVCC(快照)

  • RC(Read Committed):每次 SELECT 都生成新快照
  • RR(Repeatable Read):事务内使用同一快照(MySQL InnoDB 默认)

本质:MVCC(多版本并发控制)


九、深分页问题(LIMIT 优化)

SELECT * FROM t LIMIT 1000000, 10; -- ❌ 很慢

原因

  • MySQL 需要先扫描前 1000000 条记录
  • 再丢弃,只取 10 条

优化方案:游标分页(Keyset Pagination)

SELECT * FROM t WHERE id > 1000000 ORDER BY id LIMIT 10;

✅ 利用索引顺序定位
✅ 避免 OFFSET 扫描
✅ 性能稳定,适合大数据量翻页


索引决定 I/O,EXPLAIN 决定方向,回表和排序决定代价,分页和隔离级别决定边界。

评论

填写昵称与邮箱即可评论,无需登录。

推荐阅读