什么是覆盖索引
覆盖索引一般是针对二级索引而言的,我们知道二级索引的叶子节点存储了索引列 + 主键 id 的信息。当叶子节点包含了满足查询结果的所有数据,那么这个二级索引就被称为覆盖索引。此时,不再需要回表去查询其他列的信息,因此性能较高。
举个例子:
CREATE TABLE single_table (id INT NOT NULL AUTO_INCREMENT,key1 VARCHAR(100),key2 INT,key3 VARCHAR(100),key_part1 VARCHAR(100),key_part2 VARCHAR(100),key_part3 VARCHAR(100),common_field VARCHAR(100),PRIMARY KEY (id),KEY idx_key1 (key1),UNIQUE KEY idx_key2 (key2),KEY idx_key3 (key3),KEY idx_key_part(key_part1, key_part2, key_part3)
) Engine=InnoDB CHARSET=utf8;
-- 由于联合索引 idx_key_part 包含了 key_part1, key_part2 的完整记录,因此不需要回表。我们称它为覆盖索引。
select key_part1, key_part2 from single_table where key_part1 = 'xxx';
-- 由于联合索引 idx_key_part 包含了 key_part1, key_part2, id 的完整记录,因此不需要回表。我们称它为覆盖索引。
select key_part1, key_part2, id from single_table where key_part1 = 'xxx';
覆盖索引的利弊
好处:
- 避免 Innodb 表进行索引的二次查询(回表)
- 可以把随机 IO 变成顺序 IO 加快查询效率
对第 2 点的理解:比如对于范围查询,10 < key1 < 20。如果 key1 上有索引,那么在索引树中这些记录很可能是连续存储的,查找时为顺序 IO。回表时,由于是根据主键 id 去搜聚簇索引,而这里的 id 很可能是离散的,所以查找时为随机 IO。(如果是 IN 查询,那有可能在第一次搜二级索引的时候数据也是分布在不同数据页的,那就也是随机 IO了)
弊端:索引字段的维护 总是有代价的。因此,在建立冗余索引来支持覆盖索引时就需要权衡考虑了。这是业务 DBA,或者称为业务数据架构师的工作。