我刚刚在一些数据库讨论中听说过涵盖索引这个术语——它是什么意思?
4 回答
覆盖索引是包含查询所需的所有(可能更多)列的索引。
例如,这个:
SELECT *
FROM tablename
WHERE criteria
通常会使用索引来加快解析使用条件检索哪些行,但随后它将转到完整表来检索行。
但是,如果索引包含列column1、column2和column3,则此 sql:
SELECT column1, column2
FROM tablename
WHERE criteria
并且,如果可以使用特定索引来加快解析要检索的行,则该索引已经包含您感兴趣的列的值,因此它不必去表中检索行,但可以直接从索引中产生结果。
如果您看到典型查询使用 1-2 列来解析哪些行,然后通常添加另外 1-2 列,则也可以使用此方法,附加这些额外的列可能是有益的(如果它们全部相同) ) 到索引,以便查询处理器可以从索引本身获取所有内容。
这是一篇文章:Index Covering Boosts SQL Server Query Performance关于该主题。
覆盖索引只是一个普通的索引。如果它可以满足查询而不需要分析数据,则称为“覆盖”。
例子:
CREATE TABLE MyTable
(
ID INT IDENTITY PRIMARY KEY,
Foo INT
)
CREATE NONCLUSTERED INDEX index1 ON MyTable(ID, Foo)
SELECT ID, Foo FROM MyTable -- All requested data are covered by index
这是从 SQL Server 检索数据的最快方法之一。
覆盖索引是“覆盖”特定表所需的所有列的索引,完全不需要为给定的查询/操作访问物理表。
由于索引包含所需的列(或它们的超集),表访问可以替换为索引查找或扫描——这通常要快得多。
要涵盖的列:
- 参数化或静态条件;受参数化或恒定条件限制的列。
- 加入列;动态用于连接的列
- 选定的列;回答选定的值。
虽然覆盖索引通常可以为检索提供很好的好处,但它们确实会增加插入/更新开销;由于需要在每次更新时写入额外或更大的索引行。
连接查询的覆盖索引
覆盖索引作为连接查询的性能技术可能是最有价值的。这是因为联合查询比单表检索更昂贵且更有可能遭受高性价比问题。
- 在连接查询中,覆盖索引应该被视为每个表。
- 每个“覆盖索引”都会从计划中删除一个物理表访问,并将其替换为仅索引访问。
- 调查计划成本并试验哪些表最值得用覆盖索引替换。
- 通过这种方式,可以显着降低大型连接计划的乘法成本。
例如:
select oi.title, c.name, c.address
from porderitem poi
join porder po on po.id = poi.fk_order
join customer c on c.id = po.fk_customer
where po.orderdate > ? and po.status = 'SHIPPING';
create index porder_custitem on porder (orderdate, id, status, fk_customer);
看:
假设您有一个包含以下列的简单表,您在这里只索引了 Id:
Id (Int), Telephone_Number (Int), Name (VARCHAR), Address (VARCHAR)
想象一下,您必须运行以下查询并检查它是否使用索引,以及是否在没有 I/O 调用的情况下高效执行。请记住,您只在Id
.
SELECT Id FROM mytable WHERE Telephone_Number = '55442233';
当您检查此查询的性能时,您会感到失望,因为Telephone_Number
没有索引这需要使用 I/O 调用从表中获取行。所以,这不是一个覆盖索引,因为查询中有一些列没有被索引,这会导致频繁的 I/O 调用。
要使其成为涵盖索引,您需要在(Id, Telephone_Number)
.
更多详情请参考这篇博客: https ://www.percona.com/blog/2006/11/23/covering-index-and-prefix-indexes/