Skip to content

覆盖索引


1. 核心概念

定义

覆盖索引是指 一个索引包含查询所需的所有字段,使得执行查询时无需回表即可获取全部结果。

关键特征

  • 消除回表:避免通过二级索引找到主键后,再回主键索引树查找数据
  • 性能优势:减少I/O操作和CPU计算开销,显著提升查询速度
  • 存储代价:需要额外存储索引字段,但通过空间换时间优化查询

2. 实现原理

存储结构

非覆盖索引B+树 +---------+ +-----------------+ | 索引节点 | ----> | 主键ID | 字段A | +---------+ +-----------------+ | V 回表查询聚集索引

覆盖索引B+树 +---------+ +-----------------------------+ | 索引节点 | ----> | 主键ID | 字段A | 字段B | 字段C | +---------+ +-----------------------------+ | V 直接返回所有需要字段

执行流程对比

常规索引查询
索引树查找 -\> 获取主键 -\> 回表查聚集索引 -\> 返回结果

覆盖索引查询
索引树查找 -\> 直接返回索引中的字段值


3. 适用场景

典型场景

  1. SELECT字段较少
SELECT name, age FROM users WHERE department = 'IT';
-- 创建索引 (department, name, age)
  1. 聚合查询
SELECT COUNT(*) FROM orders WHERE status = 'PAID';
-- 创建索引 (status)
  1. 排序+过滤
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;