最近,我的一位从事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%)
此外,该过程的多个查询共享相同的模式。
我知道参数嗅探与在(重新)创建后第一次运行程序时的计划构建更相关,我认为它也受到高圈复杂性的青睐。
我的问题是:
编写过程中的查询方式(从一开始就是错误的执行计划)是否有利于参数嗅探外观或者只是恶化它们的影响?
答案 0 :(得分:0)
这里唯一的参数是a.tpt_file_id = @tpt_file_id
,如果这是参数嗅探,那么案例必须是这样的,对于某些tpt_file_id,有数千(或更多)记录,并且肯定有少数(或没有)。
生产计划与测试环境不同的另一个原因是机器不同。在生产环境中,通常会有更多的内存和更多的CPU /核心,导致优化器选择不同的计划,当然如果表中的行数不相同,它当然会导致完全不同的计划。 / p>
您可以使用option (recompile)
进行检查,以查看计划是否更改,或查看计划缓存中用于创建计划的参数值。可以在计划中最左边的对象的属性中看到。
将select distinct转换为exists子句可能是一个好主意,当然也可以正确地索引表。