《MySQL 技术内幕(第5版)》逐章精华笔记第三章

第3章:表与索引结构(完整版)

本章目标

  • 理解 MySQL 索引的物理结构(B+树)

  • 掌握最左前缀原则、覆盖索引、回表机制

  • 学会索引设计优化常见查询

  • 避免典型的“索引失效”写法


一、B+树索引结构详解

InnoDB 中所有索引,包括聚簇索引和辅助索引,底层都是 B+树 结构。

B+树 vs B树 对比

项目 B树 B+树(MySQL用)
叶子节点 存数据 存数据
非叶子节点 也存数据 只存键,不存值
查找效率 较慢 较快(更适合范围查找)
查询方式 可能终止于中间节点 必须走到叶子节点

所有值都在叶子节点,非叶子节点只用来查路。


二、最左前缀原则

联合索引的命中与否,取决于是否满足“最左前缀”原则。

✅ 规则说明:

CREATE INDEX idx_name_age ON user(name, age);

可命中索引的写法:

  • WHERE name = '张三'

  • WHERE name = '张三' AND age = 20

  • WHERE name LIKE '张%'

❌ 无法命中索引的写法:

  • WHERE age = 20(跳过了 name)

  • WHERE name LIKE '%三'(前缀模糊)

联合索引就像电话簿,是“先按姓氏 → 再按名字”顺序排列的。


三、回表与覆盖索引

回表

辅助索引的叶子节点只包含主键值,要查其他列时,需“回表”到聚簇索引查整行。

SELECT name FROM user WHERE email = '[email protected]';
-- 需要回表(索引 idx_email)

覆盖索引

如果查询的字段都在索引里,就无需回表。

SELECT email FROM user WHERE email = '[email protected]';
-- 不需要回表(完全命中 idx_email)

回表相当于查目录后翻页找正文,覆盖索引就像直接查目录就拿到答案。


四、索引失效的常见原因

类型 说明
范围后无索引 WHERE a = 1 AND b > 5,b无法命中索引
隐式类型转换 WHERE age = '20'(age 为 INT,右侧为字符串)
使用函数 WHERE DATE(create_time) = '2024-01-01' 无法使用索引
OR 连多个条件 WHERE a = 1 OR b = 2 若 b 无索引,则全表扫描
前缀模糊匹配 LIKE '%xxx' 无法使用索引

✅ 改写建议:

  • 使用区间代替函数:

-- ❌ 索引失效:
WHERE DATE(create_time) = '2024-01-01'

-- ✅ 改写后:
WHERE create_time >= '2024-01-01 00:00:00'
  AND create_time <  '2024-01-02 00:00:00'

五、实验与实践

实验 1:最左前缀规则测试

CREATE TABLE employee (
  id INT PRIMARY KEY,
  name VARCHAR(50),
  age INT,
  dept_id INT,
  INDEX idx_name_age_dept(name, age, dept_id)
);

-- 写法1:命中索引
EXPLAIN SELECT * FROM employee WHERE name = '张三';

-- 写法2:命中索引
EXPLAIN SELECT * FROM employee WHERE name = '张三' AND age = 30;

-- 写法3:无法使用索引
EXPLAIN SELECT * FROM employee WHERE age = 30;

实验 2:索引失效类型转换

-- 假设 age 是 INT 类型
EXPLAIN SELECT * FROM employee WHERE age = '30';

Extra 字段会出现 Using where 而不是 Using index


六、自测练习题

✅ 问题1:以下哪种写法不会使用索引?

CREATE INDEX idx_ab ON t(a, b);
SELECT * FROM t WHERE b = 2 AND a = 1;

答案:顺序错了,写成 a=1 AND b=2 才能命中索引。

✅ 问题2:如何判断某个查询是否“回表”?

答案:观察 EXPLAIN 的 extra 字段,是否包含 Using index

✅ 问题3:是否可以只对 name 字段加索引,就优化 like 查询?

答案LIKE '张%' 可以走索引,LIKE '%三' 无法。


七、总结图示

索引命中与否流程图:

查询字段 → 是否命中索引字段?
      ↓
按顺序书写? → 是 → 是否前缀模糊? → 否 → ✅ 使用索引
                                     ↓ 是 → ❌ 无法使用索引

下一章我们将进入 SQL 执行流程(第4章):

  • SQL 是怎么一步步执行的?

  • 优化器如何选择执行路径?

  • EXPLAIN 每列代表什么?如何分析?

你可能感兴趣的:(MySQL,mysql,笔记,数据库)