为什么在创建索引时使用INCLUDE子句?

空扰寡人 提交于 2020-02-26 03:27:17

在学习70-433考试时,我注意到您可以通过以下两种方式之一创建覆盖指数。

CREATE INDEX idx1 ON MyTable (Col1, Col2, Col3)

- 要么 -

CREATE INDEX idx1 ON MyTable (Col1) INCLUDE (Col2, Col3)

INCLUDE子句对我来说是新的。 在确定是否创建包含或不包含INCLUDE子句的覆盖索引时,您将为什么使用它以及您会建议什么准则?


#1楼

如果该列不在WHERE/JOIN/GROUP BY/ORDER BY ,而仅在SELECT子句中的列列表中。

INCLUDE子句将数据添加到最低/叶子级别,而不是在索引树中。 这使索引变小,因为它不是树的一部分

INCLUDE columns不是索引中的关键列,因此它们没有顺序。 这意味着如上所述,它对于谓词,排序等并不是真正有用。 但是,如果在关键列的几行中有剩余查找,这可能会很有用。

另一篇有关实例的MSDN文章


#2楼

基本索引列已排序,但包含的列未排序。 这样可以节省维护索引的资源,同时仍然可以在包含的列中提供数据来覆盖查询。 因此,如果要涵盖查询,则可以放置搜索条件以将行定位到索引的已排序列中,然后使用非搜索数据“包括”其他未排序的列。 它绝对有助于减少索引维护中的排序和碎片数量。


#3楼

您可以使用INCLUDE将一或多个列添加到非聚集索引的叶级,如果这样做,则可以“覆盖”查询。

假设您需要查询员工的ID,部门ID和姓氏。

SELECT EmployeeID, DepartmentID, LastName
FROM Employee
WHERE DepartmentID = 5

如果您碰巧在(EmployeeID,DepartmentID)上具有非聚集索引,则在找到给定部门的员工后,现在必须进行“书签查找”以获取实际的完整员工记录,而只是获取“姓氏”列。 如果您找到很多员工,那么就绩效而言可能会非常昂贵。

如果您在索引中包含该姓氏:

CREATE NONCLUSTERED INDEX NC_EmpDep 
  ON Employee(EmployeeID, DepartmentID)
  INCLUDE (Lastname)

那么您需要的所有信息都可以在非聚集索引的叶级中找到。 只需查找非聚集索引并找到给定部门的员工,您便拥有了所有必要的信息,并且不再需要为索引中找到的每个员工进行书签查找->这样可以节省大量时间。

显然,您不能在每个非聚集索引中包括每一列-但是,如果您确实有一些查询丢失了仅一到两列以“被覆盖”(并且被大量使用),那么将那些包含在内将非常有帮助转换为合适的非聚集索引。


#4楼

很好解释了原因(包括索引叶级中的数据)的原因。 您对此进行两点动摇的原因是,当您运行查询时,如果不包括其他列(SQL 2005中的新功能),则SQL Server必须转到聚集索引以获取其他列当新的数据页被加载到内存中时,这将花费更多的时间,并增加SQL Server服务,磁盘和内存(特定于缓冲区缓存)的负载,从而有可能将其他更常用的数据从缓冲区缓存中推出。


#5楼

我在已经给出的答案中没有看到的另一个考虑因素是,包含的列可以是不允许作为索引键列的数据类型,例如varchar(max)。

这使您可以将这些列包括在覆盖索引中。 最近,我不得不执行此操作以提供nHibernate生成的查询,该查询在SELECT中具有很多列,并具有有用的索引。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!