• SQLServer数据类型优先级对性能的影响 (转)


    问题:

             我在我的应用程序中使用简单的查询/存储过程访问一个很大的表。但执行了很长时间。在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类型。

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

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

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

    1. user-defined data types (highest)

    2. sql_variant

    3. xml

    4. datetimeoffset

    5. datetime2

    6. datetime

    7. smalldatetime

    8. date

    9. time

    10. float

    11. real

    12. decimal

    13. money

    14. smallmoney

    15. bigint

    16. int

    17. smallint

    18. tinyint

    19. bit

    20. ntext

    21. text

    22. image

    23. timestamp

    24. uniqueidentifier

    25. nvarchar (including nvarchar(max) )

    26. nchar

    27. varchar (including varchar(max) )

    28. char

    29. varbinary (including varbinary(max) )

    30. binary (lowest)

  • 相关阅读:
    ORM框架
    js获取浏览器和元素对象的尺寸
    js中的兼容问题
    JS页面上的流氓广告功能
    JS计算1到10的每一个数字的阶乘之和
    JS中 有一个棋盘,有64个方格,在第一个方格里面放1粒芝麻重量是0.00001kg,第二个里面放2粒,第三个里面放4,棋盘上放的所有芝麻的重量
    JS中99乘法表
    JS 中计算 1
    JS中判断一个数是否为质数
    JS水仙花数
  • 原文地址:https://www.cnblogs.com/qanholas/p/2802622.html
Copyright © 2020-2023  润新知