这是我参与11月更文挑战的第14天,活动详情查看:2021最后一次更文挑战
当一个索引包含了所有需要查询出来的列,那么这个索引就被称为“覆盖索引”,对应的查询被称为“索引覆盖查询”。覆盖索引的好处显而易见,直接从索引中返回查询结果,不需要进行回表。由于覆盖索引需要存储索引列的值,因此只有B树类型的索引才能作为覆盖索引。
以下面的SQL为例,
explain select col1,col2 from layout_test;
如果col1
和col2
是索引列,那么执行计划Extra
列的值为Using index
,表示这是一个索引覆盖查询;但如果为只有col1
是索引列,那么Extra
的结果不会像前者一样,在实际的查询中出现了回表操作。
使用延迟关联查询应用覆盖索引
对于下面的SQL,由于被查询的列是所有列,因此无法使用覆盖索引
EXPLAIN
SELECT *
FROM account_batch
where source_system = 'JL_MANUAL_PRC'
and source_system_name like '%酒旅手工%';
其Extra
为Using where
,这表示表示优化器需要通过索引回表查询数据,如果我们将索引列扩展至(source_system、source_system_name、id)
,使用如下查询代替
EXPLAIN
SELECT *
FROM account_batch
JOIN (SELECT id
FROM account_batch
WHERE source_system = 'JL_MANUAL_PRC'
and source_system_name like '%酒旅手工%') AS t1
ON t1.id = account_batch.id;
可以发现查询结果为Using where; Using index
,这样通过延迟关联使得第一阶段可以使用覆盖索引,然后根据第一阶段查询出的结果匹配出需要的所有列值。
使用“延迟关联查询”的优化效果需要区分场景来看
- 对于返回很大结果集的查询来说,大部分时间在读取和发送数据上,优化效果不明显。
- 对于数据集很小的查询,子查询带来的成本反而比从表中直接提取完整行更高。
- 对于数据集大但第一阶段返回的数据集较小,才能获得较好的优化效果。