0

最近,我的一位从事 SQL 开发的同事遇到了这样一个问题:一个过程在所有环境中运行良好,但在生产环境中,它拥有最多的资源。参数嗅探的典型案例,但分析器表明整个过程中只有一个查询需要非常多的时间来执行:

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% 的工作量)

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

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

我的问题是:

过程中查询的编写方式(从一开始就糟糕的执行计划)有利于参数嗅探的出现还是只会恶化它们的效果?

4

1 回答 1

0

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

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

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

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

于 2016-01-02T10:26:03.687 回答