1. MySQL索引篇:为什么是B+树?
1.1 从磁盘I/O角度理解数据结构选择
当面试官问及MySQL索引结构时,80%的候选人能说出"B+树"这个名词,但只有20%能讲清楚背后的硬件原理。让我们从计算机组成原理的视角重新审视这个问题。
机械硬盘的随机访问延迟通常在10ms左右,而SSD约为0.1ms。这意味着:
- 一次随机磁盘I/O相当于约50万次CPU指令周期
- 传统B树每个节点存储数据会导致节点容量减小
- B+树非叶子节点仅存储键值,使得单个16KB页能容纳更多索引项
具体来看,假设:
- 主键为bigint(8字节)
- 指针占用6字节
- 行数据约1KB
在B树结构中,每个节点最多存储:
(16KB)/(8+6+1024) ≈ 15个条目
而B+树非叶子节点可存储:
(16KB)/(8+6) ≈ 1142个条目
这意味着B+树的扇出(Fan-out)是B树的76倍!对于1亿条记录:
- B+树仅需log₁₁₄₂(100,000,000)≈3层
- B树需要log₁₅(100,000,000)≈7层
1.2 范围查询的链表优化
实际业务中,分页查询和范围扫描占比超过60%。B+树的双向链表设计使这类查询效率提升显著:
sql复制-- 普通范围查询
SELECT * FROM orders WHERE create_time BETWEEN '2023-01-01' AND '2023-01-31';
-- 分页查询
SELECT * FROM products ORDER BY price DESC LIMIT 10000, 20;
B树执行过程:
- 从根节点开始查找下限值
- 中序遍历到右子树
- 反复在非叶子节点间跳跃
- 涉及大量随机I/O
B+树执行过程:
- 定位到叶子节点的起始位置
- 沿链表顺序扫描
- 完全避免非叶子节点访问
- 产生连续的顺序I/O
实测对比:在1000万条记录的表中,B+树范围查询速度比B树快8-12倍
1.3 实战中的索引优化建议
- 前缀索引技巧:
sql复制-- 对长字符串列优化
ALTER TABLE users ADD INDEX idx_name_email (name(10), email(6));
- 覆盖索引陷阱:
sql复制-- 看似使用了覆盖索引
EXPLAIN SELECT user_id FROM orders WHERE status = 'paid';
-- 实际可能失效的情况
EXPLAIN SELECT user_id, order_time FROM orders WHERE status = 'paid';
- 索引合并的代价:
sql复制-- 索引合并可能不如复合索引高效
ALTER TABLE products ADD INDEX
