【发布时间】:2016-04-06 12:03:24
【问题描述】:
最近,我的一位从事 SQL 开发的同事遇到了这样一个问题:一个过程在所有环境中运行良好,但在生产环境中,它拥有最多的资源。 parameter sniffing的典型案例,但是profiler指出整个过程中只有一个查询非常耗时:
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% 的工作量)
此外,来自该过程的多个查询共享相同的模式。
我知道参数嗅探与程序在(重新)创建后第一次运行时的计划构建更相关,我认为它也受到高圈复杂度的青睐。
我的问题是:
过程中查询的编写方式(从一开始就是糟糕的执行计划)是否有利于参数嗅探的出现或只是恶化其效果?
【问题讨论】:
-
除了你的问题:你的两个建议确实会改善你的执行计划。
-
参数嗅探会在第一次运行时优化某个参数的执行计划。如果然后使用不同的参数运行,则基数可能会偏离,并且您的执行计划可能不是最佳的(或远非最佳)。重新排列查询可能会改进执行计划,然后通过参数嗅探(针对某个参数)进一步优化。两者是正交AFAICT。您可能已经通过重写进一步优化了查询,但是在应用参数嗅探之后,您可能对其他参数的计划并不理想。
-
好的,所以执行计划和参数嗅探之间没有关联。我试图说服后端开发人员注意他们如何编写查询以及他们生成的执行计划。在这种情况下,我的建议没有付诸实践,因为使用局部变量大大减少了程序的执行。感谢您指出正交性。
标签: sql-server sql-execution-plan parameter-sniffing