好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

SQLServer数据类型优先级对性能的影响

译自: http://www.mssqltips.com/sqlservertip/2749/sql-server-data-type-precedence/?utm_source=dailynewsletterutm_medium=emailutm_content=headlineutm_campaign=2012814 问题: 我在我的应用程序中使用简单的查询/存储过程访问一个很大的表。但执行

译自:

http://www.mssqltips.com/sqlservertip/2749/sql-server-data-type-precedence/?utm_source=dailynewsletter&utm_medium=email&utm_content=headline&utm_campaign=2012814

问题:

我在我的应用程序中使用简单的查询/存储过程访问一个很大的表。但执行了很长时间。在where子句中,我使用了有索引并且高选择性(selective)并且没有用函数包裹的字段。但是看起来就像没有使用索引一样,问题出在那里?

解决方案:

出现这种微秒的问题原因可能是作为参数的 数据 类型 与查询中的 数据 类型 不一致。在这种情况下,SQLServer将会要么把where中的列,要么把参数的 数据 类型 隐式转换为更高级或者更低级的 数据 类型 。当作为被查询列被转换时(转换竞争中的牺牲者),将引起扫描(scan)来满足查询请求。让我们看看以下两个例子,第一个例子使用示例 数据 库AdventureWorks,我们将通过一个客户的AccountNumber在Sales.Customer表中查询这个客户。AccountNumber这一列的 数据 类型 是varchar(10)并且上面有一个唯一索引。运行下面的查询并且查看执行计划,可以看到结果如我们所愿:

create proceduredbo.PrecedenceTest

(

@AccountNumber varchar(10)

)

as

begin

set nocount on

select *

from Sales.Customer

where AccountNumber = @AccountNumber

end

go

exec dbo.PrecedenceTest'AW00030113'

go

执行计划如下:

接着让我们在参数上做些小改动,把它改为nvarchar(10),然后重新执行语句:

alter procedure dbo.PrecedenceTest 
( 
 @AccountNumber nvarchar(10) 
) 
as 
begin 
 set nocount on 
 select *  
 from Sales.Customer 
 where AccountNumber = @AccountNumber 
end 
go 
exec dbo.PrecedenceTest 'AW00030113' 
go 

执行计划显示,优化器选择了扫描TerritoryID上的索引。


检查Filter操作,可以看到AccountNumber列上被隐式转换了 类型 来匹配传入的参数。由于 数据 类型 varchar比参数 类型 nvarchar级别更低,导致其所在的索引失效。


现在让我们验证一下,在较低级别的 数据 类型 作为查找参数下的情况。在这个例子中,Person.Person 表的LastName列是nvarchar 类型 ,并且上面存在一个可用的索引,存储过程传入的参数是varchar 类型 :

alter procedure dbo.PrecedenceTest( 
 @LastName varchar(50) 
) 
as 
begin 
 set nocount on 
 select *  
 from Person.Person 
 where LastName = @LastName 
end 
go 
exec dbo.PrecedenceTest 'Tamburello' 
go 

执行计划显示,优化器选择使用了索引查找:


点开Index Seek的详细信息,可以看到列LastName的 数据 类型 因为传入参数的原因而隐式转换成更高级的nvarchar 类型 。

当索引列不再被转换所 影响 时,优化器可以自由地选择最优执行计划。

不管你是在应用程序或者在存储过程中定义查询参数,确保查询参数中的 数据 类型 和查询列的 数据 类型 相吻合能避免索引扫描和其他转换引起的问题。


补充: 数据 类型 的 优先级 ,从高到底:

user-defined data types (highest)

sql_variant

xml

datetimeoffset

datetime2

datetime

smalldatetime

date

time

float

real

decimal

money

smallmoney

bigint

int

smallint

tinyint

bit

ntext

text

image

timestamp

uniqueidentifier

nvarchar (including nvarchar(max) )

nchar

varchar (including varchar(max) )

char

varbinary (including varbinary(max) )

binary (lowest)

查看更多关于SQLServer数据类型优先级对性能的影响的详细内容...

  阅读:34次