查询表单是否会影响参数嗅探?

时间:2016-01-02 10:03:02

标签: sql-server sql-execution-plan parameter-sniffing

最近,我的一位从事SQL开发的同事遇到了这样的问题:一个程序在所有环境中运行良好,但是生产资源最多。 parameter sniffing的典型情况,但是分析器表明整个过程中只有一个查询需要执行很多:

UPDATE  a
SET     status_id = 6
FROM    usr.tpt_udef_article_grouping_buffer a
        LEFT JOIN (SELECT DISTINCT buying_domain_id, suppl_no FROM usr.buyingdomain_supplier_article) b ON  a.buying_domain_id = b.buying_domain_id
                                                                                                        AND a.suppl_no = b.suppl_no
WHERE   a.tpt_file_id = @tpt_file_id
        AND a.status_id IS NULL
        AND b.suppl_no IS NULL

由于我偏向于开发(我的管理经验很少),我建议应该重写此查询:

  • LEFT JOIN (SELECT DISTINCT ...)替换为NOT EXISTS (SELECT 1 ...)

  • 在表usr.tpt_udef_article_grouping_buffer上放置适当的索引(SSMS建议在程序之外运行查询时减少95%)

此外,该过程的多个查询共享相同的模式。

我知道参数嗅探与在(重新)创建后第一次运行程序时的计划构建更相关,我认为它也受到高圈复杂性的青睐。

我的问题是:

编写过程中的查询方式(从一开始就是错误的执行计划)是否有利于参数嗅探外观或者只是恶化它们的影响?

1 个答案:

答案 0 :(得分:0)

这里唯一的参数是a.tpt_file_id = @tpt_file_id,如果这是参数嗅探,那么案例必须是这样的,对于某些tpt_file_id,有数千(或更多)记录,并且肯定有少数(或没有)。

生产计划与测试环境不同的另一个原因是机器不同。在生产环境中,通常会有更多的内存和更多的CPU /核心,导致优化器选择不同的计划,当然如果表中的行数不相同,它当然会导致完全不同的计划。 / p>

您可以使用option (recompile)进行检查,以查看计划是否更改,或查看计划缓存中用于创建计划的参数值。可以在计划中最左边的对象的属性中看到。

将select distinct转换为exists子句可能是一个好主意,当然也可以正确地索引表。