“INCLUDE”在索引中做了什么?

时间:2011-08-04 19:39:25

标签: sql sql-server tsql

非聚集索引中的INCLUDE是什么?

CREATE NONCLUSTERED INDEX [MyIndex] ON [dbo].[Individual] 
(
    [IndivID] ASC
)
INCLUDE ( [LastName], [FirstName]) 
WITH (SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF) ON [PRIMARY]

我知道第一部分用于WHERE子句,但INCLUDE列的用途是什么?将它们“添加到非聚集索引的叶级”有什么好处?

编辑此外,如果我已经拥有IndivID的聚集PK索引,为什么Tuning Advisor会推荐这个索引?

4 个答案:

答案 0 :(得分:8)

INCLUDE列包含索引的关联字段。它们不用于索引,但是它们被放置在构成索引的B树的叶节点中。

实质上:索引仍然只有ON [IndivID]和[IndivID]。但是,如果您的查询只需要[IndivID],[LastName]和[FirstName]的子集,则SQL在找到它在索引中搜索的[IndivID]后不需要返回该表。

参见:Covering Index

编辑:B树假设MS SQL Server。我不肯定其他实现使用相同的数据结构

Tuning Advisor(推测)::聚簇索引将整个数据行放在索引的B树的叶节点上,这占用了大量空间。如果Tuning Advisor发现您永远不会访问超过这三个字段([IndivID] + INCLUDE),它将尝试通过将其降级为非聚集索引来节省空间(并插入/更新时间)存在“重要”领域。

答案 1 :(得分:5)

INCLUDE在索引的叶级添加这些字段。基本上bt-ree没有按那些字段排序,但是一旦索引找到了它正在查找的索引字段的行,它也会立即显示其他字段。

如果您使用电话簿类比,电话簿索引中的INCLUDED字段(按LastnameFirstname排序)将为Phone Number和{{ 1}} - 你不能通过那些领域查找一个人,但是一旦你有了他们的名字就可以找到它们。

Address索引已经按设计包含了所有字段,因此CLUSTEREDINCLUDE中无效。您也不应该在非聚集索引中CLUSTER聚集字段,因为它已隐式存在于行键中。

我经常使用INCLUDE字段进行聚合。例如,如果我在INCLUDECalendarDate上有索引,我可以包含CustomerID并获取

PaidAmt

在最基本的级别,它们用于避免书签或密钥查找。

答案 2 :(得分:3)

这是在索引中作为有效负载包含的数据。它不会用于过滤,但可以返回。

例如,如果您有一个过滤年龄和返回名称的查询:

select name
from persons
where age = 42

然后,您可以为age字段创建索引,其中包含name字段。这样,数据库只能使用索引来运行整个查询,而不必从实际表中读取任何内容。

答案 3 :(得分:2)

来自MSDN - CREATE INDEX (Transact-SQL)

  

INCLUDE(列[,... n])

     

指定要添加到非聚簇索引的叶级别的非键列。

意思是,您可以向非聚集索引添加更多列 - 如果每次查询键列时返回多个字段,将它们添加到索引将提高性能,因为它们与它一起存储,即{{3 }}