mysql数据类型优先级_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

执行计划如下:

test.jsp?url=http%3A%2F%2Fmy.csdn.net%2Fuploads%2F201208%2F19%2F1345358862_4261.jpg&refer=http%3A%2F%2Fblog.csdn.net%2Fdba_huangzj%2Farticle%2Fdetails%2F7883090

接着让我们在参数上做些小改动,把它改为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上的索引。

test.jsp?url=http%3A%2F%2Fmy.csdn.net%2Fuploads%2F201208%2F19%2F1345358866_3172.jpg&refer=http%3A%2F%2Fblog.csdn.net%2Fdba_huangzj%2Farticle%2Fdetails%2F7883090

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

test.jsp?url=http%3A%2F%2Fmy.csdn.net%2Fuploads%2F201208%2F19%2F1345358870_5204.jpg&refer=http%3A%2F%2Fblog.csdn.net%2Fdba_huangzj%2Farticle%2Fdetails%2F7883090

现在让我们验证一下,在较低级别的数据类型作为查找参数下的情况。在这个例子中,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

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

test.jsp?url=http%3A%2F%2Fmy.csdn.net%2Fuploads%2F201208%2F19%2F1345358874_9225.jpg&refer=http%3A%2F%2Fblog.csdn.net%2Fdba_huangzj%2Farticle%2Fdetails%2F7883090

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

test.jsp?url=http%3A%2F%2Fmy.csdn.net%2Fuploads%2F201208%2F19%2F1345358878_8319.jpg&refer=http%3A%2F%2Fblog.csdn.net%2Fdba_huangzj%2Farticle%2Fdetails%2F7883090

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

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

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

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)

f68f2add0b68e4f9810432fce46917b7.png

本文原创发布php中文网,转载请注明出处,感谢您的尊重!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值