覆盖索引
1. 核心概念
定义
覆盖索引是指 一个索引包含查询所需的所有字段,使得执行查询时无需回表即可获取全部结果。
关键特征
- 消除回表:避免通过二级索引找到主键后,再回主键索引树查找数据
- 性能优势:减少I/O操作和CPU计算开销,显著提升查询速度
- 存储代价:需要额外存储索引字段,但通过空间换时间优化查询
2. 实现原理
存储结构
非覆盖索引B+树 +---------+ +-----------------+ | 索引节点 | ----> | 主键ID | 字段A | +---------+ +-----------------+ | V 回表查询聚集索引
覆盖索引B+树 +---------+ +-----------------------------+ | 索引节点 | ----> | 主键ID | 字段A | 字段B | 字段C | +---------+ +-----------------------------+ | V 直接返回所有需要字段
执行流程对比
常规索引查询:
索引树查找 -\> 获取主键 -\> 回表查聚集索引 -\> 返回结果
覆盖索引查询:
索引树查找 -\> 直接返回索引中的字段值
3. 适用场景
典型场景
- SELECT字段较少
SELECT name, age FROM users WHERE department = 'IT';
-- 创建索引 (department, name, age)
- 聚合查询
SELECT COUNT(*) FROM orders WHERE status = 'PAID';
-- 创建索引 (status)
- 排序+过滤
SELECT id FROM products
WHERE category = 'Electronics'
ORDER BY price DESC
-- 创建索引 (category, price)
4. 不适用场景
需要返回TEXT/BLOB等大字段 查询字段超过索引包含字段
5. 延迟关联
-- 原始查询(需回表)
SELECT * FROM articles
WHERE tag = 'MySQL'
ORDER BY created_at DESC
LIMIT 10000, 10;
-- 优化后(覆盖索引+延迟关联)
SELECT t.* FROM (
SELECT id FROM articles
WHERE tag = 'MySQL'
ORDER BY created_at DESC
LIMIT 10000, 10
) AS tmp
JOIN articles AS t ON tmp.id = t.id;