SQL Server优化器特性-隐式谓词

系统 2323 0
原文: SQL Server优化器特性-隐式谓词

我们都知道,一条SQL语句提交给优化器会产生相应的执行计划然后执行输出结果,但他的执行计划是如何产生的呢?这可能是关系型数据库最复杂的部分了.这里我为大家介绍一个有关SQL Server优化器的特性-隐式谓词,并简单介绍在此特性下如何根据场景控制优化器的行为.

   在这里我通过一个简单的实例来给大家说明下.

code

      
        CREATE
      
      
        TABLE
      
       T1 (A 
      
        INT
      
      , B 
      
        INT
      
      
        )


      
      
        CREATE
      
      
        TABLE
      
       T2 (A 
      
        INT
      
      , B 
      
        INT
      
      
        )




      
      
        set
      
       showplan_text 
      
        on
      
      
        SELECT
      
      
        *
      
      
        FROM
      
       T1 
      
        INNER
      
      
        JOIN
      
       T2 
      
        ON
      
       T1.A 
      
        =
      
      
         T2.A




      
    

可以看出我的语句执行计划中优化器为我添加了T2.A=0这个谓词.如图1-1

                                                                图1-1

优化器根据语义逻辑判断,在不改变结果集的前提下认为提前在T2表中过滤出T2.A=0的结果集再参与下面运算可以提升效率,这样在未征得我们同意的情况下他就这样做了:)

这就是 隐式谓词

既然这是SQL Server优化器的默认行为,那在我们自己要控制优化器行为的时候就少不了与其默认行为冲突.这里还是通过简单的实例说明.

code

 

      
        select
      
      
        @@VERSION
      
      
        SELECT
      
      
        *
      
      
        FROM
      
       T1 
      
        inner
      
       hash 
      
        JOIN
      
       T2 
      
        ON
      
       T1.A 
      
        =
      
      
         T2.A


      
      
        WHERE
      
       T1.A 
      
        =
      
      
        0
      
    

可以看到,我为sql加了个hash join的hint结果就出现了错误.如图1-2

 

                                                        图1-2

原因: 默认的情况下优化器为我们加上了T2.A=0,t1,t2采用了相同的过滤条件,这时T1.A=T2.A自身的意义就不存在了,而hash join自身又需要等值链接(equijoin),此时报错就出现了.

延伸: 其实在此种情况下select中检索凑到一起就可以了,抛错误让开发人员郁闷.微软注意到了这点,SQL2012中上述查询就没有问题了.如图1-3

 

                                        图1-3

问题来了(不是挖掘机哪家强),如果我用了hint这种情况又该怎么办呢?就我们刚才的语句分析,hash join需要等值链接,可以根据表的定义规避他的隐式谓词特性造成的这个问题.

Where 条件中换成不等值不就可以了:)

Code

      
        SELECT
      
      
        *
      
      
        FROM
      
       T1 
      
        inner
      
       hash 
      
        JOIN
      
       T2 
      
        ON
      
       T1.A 
      
        =
      
      
         T2.A


      
      
        WHERE
      
       T1.A 
      
        >-
      
      
        1
      
      
        and
      
       t1.A
      
        <=
      
      
        0
      
    

 

关于性能

可以看出在参与JOIN操作之前,优化器为我们过滤掉一部分数据,使得Join的消耗减轻,这是件好事儿,但凡事都有两个方面,为过滤掉的这部分数据他不是免费的,有时候可能会加重负担.

这里介绍一个 trace flag 2324 ,他可以使优化器不采取隐式谓词行为,在特殊的场景下可以让我们的执行计划发挥的更好.

这里我通过一个简单的实例说明下.

code

      
        select
      
      
        *
      
      
        from
      
       aaa 
      
        inner
      
      
        join
      
      
         bbb 


      
      
        on
      
       aaa.ProductID
      
        =
      
      
        bbb.ProductID


      
      
        where
      
       aaa.ProductID
      
        >
      
      
        1000
      
      
        and
      
       aaa.ProductID
      
        <
      
      
        1500
      
      
        go
      
      
        select
      
      
        *
      
      
        from
      
       aaa 
      
        inner
      
      
        join
      
      
         bbb 


      
      
        on
      
       aaa.ProductID
      
        =
      
      
        bbb.ProductID


      
      
        where
      
       aaa.ProductID
      
        >
      
      
        1000
      
      
        and
      
       aaa.ProductID
      
        <
      
      
        1500
      
      
        option
      
      (querytraceon 
      
        2324
      
      )
      
        --
      
      
        --禁用隐性谓词
      
    

可以看到由于由于隐式谓词在特殊的场景中(如数据分布比较倾斜.实例中ProductID=1001站了bbb表中的80%数据)过滤后的join反而不如整体数据参加join来得更快.如图1-4

 

                                                                      图1-4

此处实例只为简单说明作用,实际生产中可能因为统计信息问题使得优化器采用了不合理的运算符(如对bbb中采用seek,则消耗巨大,而统计信息自身又不易更新)使得执行计划不合理影响整体性能.感兴趣的朋友可以自行测试.

注:TF2324只对不等值谓词起作用.等值谓词如果想规避隐性谓词,参考挖掘机的例子:)

结语: 凡事都具有两面性,隐式谓词在绝大多数场景中是个很好的策略,微软也在一步步完善.但在优化器无法合理处理时,就需要我们人为介入.

 

SQL Server优化器特性-隐式谓词


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论