日期:2014-05-16 浏览次数:20546 次
在执行计划中我们经常会看到KeyLookup和RIDLookup操作,而且Cost很大,具体什么是Key Lookup和RID Lookup:
RIDLookup是在使用提供的行标识符(RID) 在堆上进行的书签查找
KeyLookup运算符是在具有聚集索引的表上进行的书签查找
区别是 Key Lookup通过聚集索引键值进行查找,RID Lookup是通过堆的行标识符(FileID:PageID:SlotNumber)查找,由于都需要额外的IO完成查询,所以这两个操作都是很耗费资源的。
SQLServer 2005提供了Include索引可以帮助消除RID Lookup和Key Lookup。
下面我们做个测试:
useAdventureWorks
go
SELECT [sod].[ProductID],
[sod].[OrderQty],
[sod].[UnitPrice]
FROM [Sales].[SalesOrderDetail] sod
WHERE [sod].[ProductID]= 897
执行计划:
因为索引[IX_SalesOrderDetail_ProductID]只包含了[ProductID]列,无法直接获得[OrderQty]和[UnitPrice],所以需通过Clusterindex找到这两列数据,就会产生Key Lookup的操作(98% cost).
下面我修改[IX_SalesOrderDetail_ProductID],增加Include [OrderQty]和[UnitPrice]列。
CREATE NONCLUSTEREDINDEX[IX_SalesOrderDetail_ProductID]ON [Sales].[SalesOrderDetail]
(
[ProductID] ASC
)
INCLUDE( [OrderQty],
[UnitPrice])
重新执行,产生新的执行计划,我们只看到IndexSeek操作:
使用Include Index有以下优点:
·重新设计索引键大小较大的非聚集索引,以便只有用于搜索和查找的列为键列。使覆盖查询的所有其他列成为非键列。这样,将具有覆盖查询所需的所有列,但索引键本身较小,而且效率高。
· 将非键列包含在非聚集索引中,以避免超过当前索引大小的限制(最大键列数为 16,最大索引键大小为 900字节)。数据库引擎计算索引键列数或索引键大小时,不考虑非键列。
由于不将Inculde字段当做索引键处理,可以减少Index的层级,查询IO也相应减少(对性能影响很大),同时也可以降低存储空间。 下面我们通过一个测试来看一下索引键值对索引层级的影响。
1.首先创建两张表,IndexLevel_Small ID Int型为主键(键值很小),IndexLevel主键ID为字符型(长度900,索引运行的最大字节数)。
CREATE TABLE [dbo].[IndexLevel_Small](
[ID] [int] NOT NULL,--Primary Key
[Name][varchar]