跳至正文
来两杯美式
返回

MySQL 知识系列(二):索引结构与查询原理

By 来两杯美式
发布于

为什么需要索引

索引的三大价值(减少扫描量/避免排序/随机 I/O 转顺序 I/O)

  1. 减少扫描量:存储引擎直接定位到目标行,不再全表扫描
  2. 避免临时表排序:B+ 树天然有序,ORDER BY 可直接走索引
  3. 随机 I/O 转顺序 I/O:范围查询时顺着叶子节点链表扫描

可用做索引的数据结构演进

线性查找 / 二分查找

二叉搜索树 / AVL

B 树

B 树 3 层结构(根 / 中间节点 / 叶子节点均存数据)

B+ 树(InnoDB 实际采用)

B+ 树(叶节点带链表指针,非叶节点只存索引)

B+ 树对 B 树的关键改进:

  1. 只叶子节点存数据,非叶节点只存索引——同样大小的页能装更多索引项,树更矮
  2. 叶子节点之间用链表串联——范围查询只需在叶子节点顺序扫描
  3. 数据集中在叶子节点——磁盘预读(read-ahead)命中率更高

InnoDB 一般使用 2~4 层 B+ 树,根节点常驻内存,3 次磁盘 I/O 即可命中任何数据。

Hash

聚簇索引 vs 非聚簇索引

InnoDB 聚簇 vs MyISAM 非聚簇索引对比

维度InnoDB(聚簇)MyISAM(非聚簇)
主键索引叶子节点完整数据行数据行地址
辅助索引叶子节点主键值数据行地址
数据文件与主键索引合一独立存储
辅助索引查询二次查找(回表)一次定位地址
聚簇索引数量只能 1 个无此概念

InnoDB 必须有聚簇索引,规则:

  1. 有主键 → 主键就是聚簇索引
  2. 没有主键 → 第一个声明的唯一非空索引
  3. 都不满足 → InnoDB 内部生成 6 字节的 ROW_ID 隐藏主键

“回表”是什么? 当你用辅助索引(比如 idx_name)查询时,InnoDB 先在辅助索引树上找到主键值,再回到聚簇索引树上按主键查完整数据——这就是”两次 B+ 树查找”,也叫回表。

💡 优化回表SELECT id, name FROM user WHERE name = 'a' 这种查询,如果辅助索引已经”覆盖”了需要的所有列(id 是主键,name 是索引列),不需要回表——这就是覆盖索引(Covering Index)的精髓。

Btree 索引的 4 大使用限制

Btree 索引使用限制清单

  1. 不从最左前缀开始查询,无法使用索引
    • WHERE name = 'a' AND age = 10 命中联合索引 (name, age)
    • WHERE age = 10 不命中(跳过了 name)
  2. 不能跳过索引中的列
    • WHERE name = 'a' AND addr = '北京' 只用到了 name,addr 走全表扫描
  3. NOT IN / <> 操作无法使用索引
  4. 范围查询(><BETWEEN)右边的列无法使用索引
    • WHERE name = 'a' AND age > 10 AND addr = '北京' 只用到 name + age 范围

下一篇会讲 InnoDB 并发的核心:锁机制(全局锁/表级锁/MDL/行级锁)+ MVCC + 间隙锁与幻读的解决


分享这篇文章:
通过邮件分享这篇文章✓ 链接已复制
所属专题
MySQL
第 2 / 9 篇
查看系列全部文章
  1. 01.MySQL 知识系列(一):整体架构与存储引擎
  2. 02.MySQL 知识系列(二):索引结构与查询原理
  3. 03.MySQL 知识系列(三):锁机制与并发控制
  4. 04.MySQL 知识系列(四):日志系统:redo log、undo log、binlog
  5. 05.MySQL 知识系列(五):隔离级别、Spring 事务与查询流程
  6. 06.MySQL 知识系列(六):SQL 注入、版本特性与容量评估
  7. 07.MySQL 知识系列(七):SQL 调优(一)—— EXPLAIN 执行计划
  8. 08.MySQL 知识系列(八):SQL 调优(二)—— 索引设计与调优工具
  9. 09.MySQL 知识系列(九):CASE 语句、乐观锁与悲观锁实战

上一篇
MySQL 知识系列(三):锁机制与并发控制
下一篇
MySQL 知识系列(一):整体架构与存储引擎