`
java-mans
  • 浏览: 11630877 次
文章分类
社区版块
存档分类
最新评论

消除Key Lookup和RID Lookup Part1:使用Include Index

 
阅读更多

在执行计划中我们经常会看到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](3000)NULL)

CREATE TABLE [dbo].[IndexLevel](

[ID][varchar](900)NOTNULL,--PrimaryKey

[Name][varchar](3000)NULL,

) on primary

2.对两张表分布插入100000条数据:

DECLARE @ID ASVARCHAR(900)

DECLARE @NAME ASVARCHAR(3000)

DECLARE @INT ASINT

set @INT = 1

WHILE @INT <100000

BEGIN

SET @ID = REPLICATE('A',880)+CONVERT(varchar(10),@INT)

set @INT+=1

INSERT INTO dbo.IndexLevelvalues(@ID,REPLICATE('a',3000))

END

DECLARE @ID ASVARCHAR(900)

DECLARE @NAME ASVARCHAR(3000)

DECLARE @INT ASINT

set @INT = 1

WHILE @INT <100000

BEGIN

SET @ID = REPLICATE('A',880)+CONVERT(varchar(10),@INT)

set @INT+=1

INSERT INTO dbo.IndexLevelvalues(@ID,REPLICATE('a',3000))

END

3.查一下索引级别:

SELECT OBJECT_NAME(object_id)as TableName,index_depth,page_count,fragment_countFROMsys.dm_db_index_physical_stats(DB_ID('FNDBLogTest'),OBJECT_ID('dbo.IndexLevel'),null,null,null)

union

SELECT OBJECT_NAME(object_id)as TableName,index_depth,page_count,fragment_countFROMsys.dm_db_index_physical_stats(DB_ID('FNDBLogTest'),OBJECT_ID('dbo.IndexLevel_Small'),null,null,null)

TableNameindex_depthpage_count fragment_count

--------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------

IndexLevel 8 54999 28607

IndexLevel_Small 3 50000 195

(2 row(s)affected)


4. 在两张表中查询记录,看IO状况:

set statisticsioon

go

select * from dbo.IndexLevel where ID = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1'

go

set statisticsiooff

go

(1 row(s)affected)

Table'IndexLevel'. Scancount 0, logical reads 8,physicalreads 0, read-ahead reads 0, lob logical reads 0, lob physical reads0, lobread-ahead reads 0.

set statisticsioon

go

select * from dbo.IndexLevel_Small whereID= 2

go

set statisticsiooff

go

(1 row(s)affected)

Table'IndexLevel_Small'.Scan count 0, logicalreads 3,physical reads 0, read-ahead reads 0, lob logical reads 0, lobphysical reads 0,lob read-ahead reads 0.

我们看到索引键值为900的表查找一条记录需要8次逻辑IO,而字符型为主键的表只需要3次逻辑IO,如果查询数据量大的话性能差距就很明显了。由于SQL Server 2000中只能用compositeindex(所有的列都需要作为索引页)解决这个问题,所以SQLServer 2005 的Include index相比于compositeindex性能要好很多。

如何创建Include Index参考:Create Indexes withIncluded Columns

http://msdn.microsoft.com/en-us/library/ms190806.aspx

还有另外一种办法也可以达到相同的效果,参考:消除Key Lookup和RID Lookup Part2:索引交集和索引Join

http://blog.csdn.net/smithliu328/article/details/7835497

分享到:
评论

相关推荐

    lookup函数的使用

    "Excel Lookup 函数的使用和经典查找方式" Lookup 函数是 Excel 中最常用的查找函数之一,它可以帮助用户快速地查找和匹配数据。本文将详细介绍 Lookup 函数的用法、语法、参数意义、应用实例,以及经典的条件查找...

    【含源码和addin】RevitLookup 2020

    用法:将RevitLookup.addin和RevitLookup.dll放到C:\ProgramData\Autodesk\Revit\Addins\2019下即可。(如果不能正常使用,请用Visual Studio打开源码,将项目所需的引用更新到正确的路径,编译生成RevitLookup.dll...

    解决docker报错dial tcp lookup registry-1.docker.io

    解决docker报错dial tcp lookup registry-1.docker.io

    RevitLookup2021.rar

    1. **元素信息查看**:RevitLookup允许用户在运行时检查Revit模型中的任何元素,包括其属性、参数、类型信息和层次结构。这对于调试自定义族或Revit API应用程序非常有用,因为它可以帮助开发者理解元素是如何组织和...

    vc错误查看工具lookup

    VC错误查看工具Lookup是一款专为Visual C++开发者设计的实用工具,它主要帮助用户解析和理解在编程过程中遇到的各种编译、链接或者其他错误代码。这些错误代码通常以数字形式出现,对于初学者或者不熟悉的开发者来说...

    RevitLookup-2021.0.0.13

    RevitLookup是一款强大的Revit插件,主要用于Revit二次开发中的调试和分析工具。它能够帮助用户在Revit环境中深入洞察模型元素的属性和结构,从而更好地理解和优化BIM(建筑信息模型)项目。RevitLookup-2021.0.0.13...

    RevitLookup-2016.0.0.6 已编译 直接使用

    revit开发必备工具 本包中是已经编译过的文件,可以直接使用 以下是编译过程 和 原始插件下载地址------------------------- 下载 RevitLookup for Revit 2016 ...

    Revit Lookup2017-2020.zip

    Revit Lookup是一款强大的Revit插件,主要用于Revit二次开发中的数据查询和分析。这款工具在Revit API(应用程序编程接口)的开发过程中扮演着重要角色,帮助开发者深入理解Revit模型的数据结构和元素属性。 Revit...

    Delphi中ADOQuery使用了lookup字段后出现未知错误解决办法

    ### Delphi中ADOQuery使用了lookup字段后出现未知错误解决办法 在Delphi开发环境中,使用ADOQuery组件处理数据库查询时,经常会遇到一些常见的问题,尤其是涉及到lookup字段时。lookup字段通常用于显示一个表中的...

    NetBeans lookup的例子

    在NetBeans 8.0中,你可以使用以下步骤来创建和使用Lookup查询的例子: 1. **创建NetBeans模块项目**:启动NetBeans IDE,创建一个新的NetBeans Module Project。 2. **定义服务接口和服务实现**:在项目中创建一个...

    RevitLookup 2015 已编译

    RevitLookup是一款强大的Autodesk Revit二次开发工具,专为Revit API(应用程序接口)的调试和探索而设计。这款插件由Revit社区的开发者们贡献,它为Revit模型中的元素提供了一种直观的方式来查看和理解其内在的数据...

    LOOKUP函数处理内存数组

    1. **单行/单列查找**:如果`lookup_array`和`result_array`都是单行或单列,LOOKUP将进行线性查找。这意味着它会从上到下顺序搜索,直到找到匹配的`lookup_value`,然后返回该行或列对应的结果。 2. **向量查找**...

    Revit2019 二次开发工具 AddinManager 和 RevitLookup 直接使用

    本教程主要关注Revit2019的两个关键二次开发工具:AddinManager和RevitLookup。 AddinManager是一个插件管理工具,它使得Revit用户能够方便地安装、卸载和管理自定义的Revit插件。在Revit的二次开发过程中,Addin...

    Revit2020 二次开发工具 AddinManager 和 RevitLookup 直接使用

    本资源提供了两个重要的Revit2020二次开发工具:AddinManager和RevitLookup。 AddinManager是一个插件管理工具,它帮助开发者更加方便地管理和控制Revit中的自定义插件。在Revit默认情况下,开发者需要手动编辑Add...

    Lookup Table导入表格

    在 Lookup Table 中,数据可以来自多种来源,包括 TXT 文件和 EXCEL 表格。下面将分别介绍如何将这两种类型的文件导入到 Lookup Table 中。 TXT 文件导入 首先,需要在当前目录下创建一个 TXT 文件,例如 desktop ...

    RevitLookup2018(包含dll和addin文件)

    RevitLookup2018是一款强大的插件工具,专为Autodesk Revit 2018设计,用于帮助用户在Revit环境中进行调试和检查模型数据。...因此,熟悉和掌握RevitLookup的使用方法对于Revit 2018的用户来说是相当有价值的。

    DELPHI LOOKUP的DEMO

    DELPHI LOOKUP的DEMO是一个使用Delphi编程语言实现的数据库联动下拉框示例。在数据库应用开发中,DBLookupComboBox控件通常用于显示一个与数据库字段相关的下拉列表,用户可以从列表中选择一个值,这个值将与数据库...

Global site tag (gtag.js) - Google Analytics