在研究了70-433考试,我注意到您可以通过以下两种方式之一创建一个覆盖索引。
CREATE INDEX idx1 ON MyTable (Col1, Col2, Col3)
- 要么 -
CREATE INDEX idx1 ON MyTable (Col1) INCLUDE (Col2, Col3)
该include子句是新的我。 为什么要使用它,你会在确定是否要创建带或不带include子句覆盖索引有什么建议的准则?
在研究了70-433考试,我注意到您可以通过以下两种方式之一创建一个覆盖索引。
CREATE INDEX idx1 ON MyTable (Col1, Col2, Col3)
- 要么 -
CREATE INDEX idx1 ON MyTable (Col1) INCLUDE (Col2, Col3)
该include子句是新的我。 为什么要使用它,你会在确定是否要创建带或不带include子句覆盖索引有什么建议的准则?
如果列不在WHERE/JOIN/GROUP BY/ORDER BY
,但只能在列列表SELECT
子句。
该INCLUDE
子句最低/叶级增加的数据,而不是在索引树。 这使得该指数小,因为它不是树的一部分
INCLUDE columns
不在索引键列,所以他们是没有顺序的。 这意味着它不是谓词真正有用的,正如我上面提到的排序等。 但是,如果你有从键列几行的剩余查询(S) 可能是有用
另MSDN文章用工作实例
你会使用INCLUDE到一个或多个列添加到非聚集索引的叶级,如果这样做,就可以“覆盖”查询。
想象一下,你需要查询一个员工的ID,部门ID和姓氏。
SELECT EmployeeID, DepartmentID, LastName
FROM Employee
WHERE DepartmentID = 5
如果你碰巧有(雇员,DepartmentID的)一个非聚集索引,一旦你找到一个给定部门的职员,你现在要做的“书签查找”,以获得实际的全员工的记录,只是为了获得姓氏列。 这可以在性能方面得到相当昂贵,如果你发现有很多的员工。
如果您已经包含在索引名字:
CREATE NONCLUSTERED INDEX NC_EmpDep
ON Employee(EmployeeID, DepartmentID)
INCLUDE (Lastname)
那么所有你需要的信息是在非聚集索引的叶级可用。 只需在非聚集索引寻找和发现你的员工对于给定的部门,你拥有所有必要的信息,并在索引中找到的每个员工书签查找不再需要 - >您节省大量的时间。
很显然,你不能包括在每一个非聚集索引的每一列 - 但是如果你有哪些缺失只是一个或两列被“覆盖”(和习惯很多)查询,它可以是非常有帮助的包括那些成合适的非聚集的索引。
这个讨论是错过了重要的一点:现在的问题是不是如果“非键列”是更好地为包括指数 -columns或包括 -columns。
现在的问题是它是多么昂贵,使用了包括机制,包括那些不是真的需要在索引中的列? (通常不其中子句的一部分,但通常包括在选择)。 所以,你的困境始终是:
其中:ID1,ID2 ... IDN往往是在限制和COL1,COL2使用的列...科隆被列往往选择,但通常限制在不使用
(包括所有这些列的索引键的一部分的选项只是一直傻傻(除非他们也在限制使用) - 因为它总是会更贵,以保持以来,该指数必须更新,甚至当排序“钥匙”并没有改变)。
因此,使用选项1或2?
答:如果您的表很少更新-主要是插入/删除了-那么它是相对便宜的使用包括机制,包括一些“热柱”(即通常用于在选择-但不是经常上限制使用),因为插入/删除需要索引进行更新/无论如何分类,因此很少额外的开销与存储关闭了一些额外的列,而已经更新索引相关。 开销是额外的内存和CPU用来存储在索引冗余信息。
如果考虑到添加列的包括柱经常更新(不包括指数- 关键 -columns更新) - 或 -如果它是这么多的该指数变得接近你的表的副本-使用选项1我建议! 此外,如果加入一定包括列(S)原来就没有任何性能差异 - 你可能想跳过添加他们:)确认他们是有用的想法!
每值相同的行中键的平均数量(ID1,ID2 ... IDN)可能是一些重要性,以及。
注意,如果一个柱-其被添加作为索引的一个包括 -column -用于在限制 : 只要索引作为这样,可以使用 (基于针对索引- 键 -columns限制) -然后将SQL Server匹配针对索引(叶节点值),而不是去周围表本身的昂贵的方式列限制。
基本指数列排序,但包含的列进行排序。 这在维护索引,同时还使其能够提供在包括列中的数据来覆盖查询节省了资源。 所以,如果你想覆盖查询,就可以把搜索条件查找行进入指数的排序列,但随后“包括”另外,与非搜索数据未排序的列。 这肯定与减少索引维护分拣量和破碎帮助。
为什么原因(包括索引的叶级中的数据)已经很好地解释。 你提供有关这两震动的原因是,当你运行你的查询,如果你没有其他列包括(SQL 2005中的新功能),在SQL Server有去聚集索引,以获得额外的列这需要更多的时间,并增加了更多的负载给SQL Server服务,盘,和存储器(高速缓冲存储器是特异性的)作为新的数据页被加载到存储器,潜在地压出缓存的其他更经常需要的数据。
我没有在已经给出的答案,看到另外一个consideraion,是包含的列可以是不允许作为索引键列,如VARCHAR(max)数据类型。
这使您可以包括一个覆盖索引这些列。 最近,我这样做是为了提供一个NHibernate的生成的查询,其中有很多选择列的,一个有用的指标。
还有就是要联到索引定义的所有列的总大小的限制。 ,虽然说,我从未有过那片广阔的创建索引。 对我来说,更大的好处是,你可以覆盖更多的查询与已包含的列,因为他们没有任何特定的顺序来定义做一个索引。 想想是在索引中的索引。 一个例子是STOREID(其中STOREID是低选择性意味着每个店有很多客户的关联),然后客户人口统计数据(姓氏,名字,出生日期):如果你只是内嵌顺序的那些列(STOREID,姓氏,名字,出生日期),你只能高效地搜索,而您知道STOREID和姓氏的客户。
在另一方面,在STOREID定义索引和包括姓氏,名字,出生日期栏将让你在本质上做STOREID 2 seeks-索引断言,然后寻求在任何包含的列的谓词。 这将让你覆盖所有可能的搜索permutationsas只要它STOREID开始。