在上面的例子中,我们了解了SQL Server如何使用索引查找来有效地获取满足谓词上的数据,然而,我们也知道非聚集索引并不覆盖表的所有列.试想一下,若我们有这样一个在非聚集索引键上的谓词查询:select查询的列并未被索引覆盖,当SQL Server在非聚集索引上查找时,将会丢失一些需要的列,与之相反,如果在聚集索引或唯上执行扫描时,将获取所有列,由于要扫描表的每一行,其操作显然不是很有效.以下的查询就是如此:
SELECT [OrderId], [CustomerId] FROM [Orders] WHERE [OrderDate] = '1998-02-26'上面的查询与先前我们进行索引查找的用到的查询一样,唯一不同的是,这里我们选择了两列:OrderID和CustomerID.非聚集索引OrderDate列仅覆盖OrderID列.
SQL Server具有处理这一问题的方法,对于从非聚集索引中获取的每一行,它可能查询包含在聚集索引中的剩余列(这里是CustomerID),我们称该操作为"书签查询".书签查询是一个指向堆或聚集索引行的指针.SQL Server在非聚集索引中存储每一行的书签,这样一来,可以从非聚集索引直接转向基表中相对应的记录行.
下图说明了书签查询先在非聚集索引叶级上查找,然后从指向聚集索引的数据页中查找的情况。
SQL Server 2000使用指定的迭代器来实现书签查询,通过文本计划可以看出索引查找与书签查询迭代器:
|--Bookmark Lookup(BOOKMARK:([Bmk1000]), OBJECT:([Orders]))
|--Index Seek(OBJECT:([Orders].[OrderDate]),
SEEK:([Orders].[OrderDate]=Convert([@1])) ORDERED FORWARD)
下图为SQL Server 2000中的图形查询计划:
在SQL Server 2005中将使用嵌套循环联接和聚集索引查找来实现,仅当基表含有聚集索引或RID查询(基表是堆),SQL Server 2005中的查询计划与SQL Server 2000中的计划有些不同,但逻辑上是相同的.聚集索引查找就是通过LOOKUP关键来实现的一种书签查询或通过属性Lookup=”1”.以下是SQL Server 2005的图形查询计划和文本查询计划:
|--Nested Loops(Inner Join, OUTER REFERENCES:([Orders].[OrderID])) |--Index Seek(OBJECT:([Orders].[OrderDate]), SEEK:([Orders].[OrderDate]='1998-02-26') ORDERED FORWARD) |--Clustered Index Seek(OBJECT:([Orders].[PK_Orders]), SEEK:([Orders].[OrderID]=[Orders].[OrderID]) LOOKUP ORDERED FORWARD)来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/355374/viewspace-495810/ ,如需转载,请注明出处,否则将追究法律责任。