在学习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
不是索引中的关键列,因此它们没有顺序。 这意味着如上所述,它对于谓词,排序等并不是真正有用。 但是,如果在关键列的几行中有剩余查找,这可能会很有用。
#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中具有很多列,并具有有用的索引。
来源:oschina
链接:https://my.oschina.net/u/3797416/blog/3162552