MSSQL索引优化之移除键查找(书签查找)或RID查找
Tags: MSSQLSQL Server优化索引优化
简介
从SQL Server 2005 SP1 及以前的版本,键查找被称为书签查找。
当查询请求少量数据时,SQL Server 优化器将试图使用在查询结果列或包含在WHERE语句中列的非聚集索引,检索数据。如果查询请求的数据没有呈现在非聚集索引中,SQL Server 必须返回数据页去获取这些列中的数据。无论表是否有聚集索引,查询仍将到表或聚集索引中检索数据。
上面的场景中,如果表有聚集索引,其被称为键查找 (key lookup,或书签查找bookmark lookup);如果表没有聚集索引,但是有一个非聚集索引,其被称为 RID 查找。这种操作消耗很大。为优化任何包含键查找或RID查找的查询,其应该从查询计划中被移除。有两种不同的移除键查找或RID查找的方法。
在弄清楚这两种方法之前,我们将创建没有聚集索引的测试表,激发RID查找。RID 查找是使用提供的行标识符(row identifier ,RID)在堆上的书签查找。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | --创建有几个列的表 OneIndex CREATE TABLE OneIndex(ID INT, FirstName VARCHAR(100), LastName VARCHAR(100), City VARCHAR(100)); GO --向表中插入10万行记录 INSERT INTO OneIndex (ID,FirstName,LastName,City) SELECT TOP 100000 ROW_NUMBER() OVER (ORDER BY a.name) RowID, 'Bob', CASE WHEN ROW_NUMBER() OVER (ORDER BY a.name)%2 = 1 THEN 'Smith' ELSE 'Brown' END, CASE WHEN ROW_NUMBER() OVER (ORDER BY a.name)%999 = 1 THEN 'Las Vegas' WHEN ROW_NUMBER() OVER (ORDER BY a.name)%10 = 1 THEN 'New York' WHEN ROW_NUMBER() OVER (ORDER BY a.name)%10 = 5 THEN 'San Marino' WHEN ROW_NUMBER() OVER (ORDER BY a.name)%10 = 3 THEN 'Los Angeles' ELSE 'Houston' END FROM sys.all_objects a CROSS JOIN sys.all_objects b; GO |
现在让我们运行下面的查询语句,并检查查询计划
因为表上没有索引,执行的是全表扫描(Table Scan)。我们将在表上创建一个聚集索引,然后再次检查执行计划。
1 2 | -- 创建聚集索引 CREATE CLUSTERED INDEX [IX_OneIndex_ID] ON [dbo].[OneIndex] ( [ID] ASC); |
现在再次运行如下查询
1 2 | SELECT ID, FirstNameFROM OneIndexWHERE City = 'Las Vegas' GO |
执行计划清晰的表明,当表上创建聚集索引后,Table Scan 现在转变为 Clustered Index Scan。在这两种情况下,基本表都是完全扫描的,表上没有搜索。
现在,让我们看一下查询的WHERE 语句。直观上来看,如果我们在表上创建包含WHERE语句中字段列的索引,可能会获得性能提升。让我们在表上创建一个非聚集索引,然后再检查执行计划。