MySQL面试题:索引的底层原理与优化策略
题目:
请解释MySQL中B+树索引的底层结构及其优势,并结合实际场景说明如何通过索引优化查询性能。在哪些情况下索引可能失效?如何避免?
参考答案
-
B+树索引的底层结构
- 树形结构:B+树是一种多路平衡搜索树,非叶子节点仅存储键值(索引字段),叶子节点存储完整数据或主键(聚集索引与非聚集索引的区别)。
- 顺序链表:所有叶子节点通过双向链表连接,支持高效的范围查询(如
BETWEEN
或ORDER BY
) - 层级与IO优化:B+树的层级较低(通常3-4层),每个节点存储大量键值,减少磁盘IO次数。例如,假设单页存储16KB数据,3层B+树可支持千万级数据量
优势:
- 范围查询高效:叶子节点的链表结构可直接遍历,避免B树需要回溯非叶子节点的问题
- 减少磁盘IO:非叶子节点不存储实际数据,单页可容纳更多索引键,降低树的高度
-
索引优化查询性能的实践场景
- 覆盖索引:查询字段均在索引中时,引擎直接从索引获取数据,避免回表操作。例如:
SELECT user_id FROM users WHERE age > 20; -- 若索引包含(user_id, age)
- 最左前缀原则:联合索引
(a, b, c)
可优化WHERE a=1 AND b=2
,但无法优化WHERE b=2
- 索引下推(ICP):MySQL 5.6+支持将WHERE条件过滤下推到存储引擎层,减少回表次数。例如:
SELECT * FROM users WHERE name LIKE '张%' AND age > 25; -- 联合索引(name, age)时生效
索引失效的常见场景及规避方法
- 隐式类型转换:字段类型与查询条件类型不一致(如字符串字段用数字查询)会导致索引失效
- 函数或表达式操作:对索引字段使用函数(如
YEAR(create_time)
)或计算(如price*2 > 100
)会破坏索引有序性 - 前导模糊查询:
LIKE '%keyword'
无法利用索引,建议改用LIKE 'keyword%'
或全文索引 - OR条件不当:若OR两侧字段不全有索引,可能触发全表扫描。例如:
SELECT * FROM users WHERE name = '张三' OR age > 30; -- 若仅name有索引,仍会全表扫描
-
索引设计与维护建议
- 选择性原则:优先为区分度高的字段(如唯一ID)建索引,避免对低区分度字段(如性别)建索引
- 定期分析索引效率:使用
SHOW INDEX FROM table
查看索引基数(Cardinality),低基数索引可考虑删除 - 避免冗余索引:如联合索引
(a, b)
已存在,单独索引(a)
可能冗余
考察点
- 原理理解:是否掌握B+树结构与MySQL索引设计的关联。
- 实战能力:能否结合实际场景提出优化方案,并识别索引失效风险。
- 扩展知识:对覆盖索引、索引下推等高级特性的了解深度。
参考难度:⭐⭐⭐⭐(高级)