【问题标题】:Does query form have an influence on getting into parameter sniffing?查询表单是否对进入参数嗅探有影响?
【发布时间】: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


【解决方案1】:

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

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

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

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

【讨论】:

  • 是的,该参数正在嗅探,采用的快速解决方案是声明一个局部变量并将参数分配给它。这解决了问题并且查询保持不变(尽管糟糕的执行计划非常清晰并且在每个环境中都可以重现)。我想知道糟糕的计划和参数嗅探之间可能存在联系,因为这是第一个经常发生这种情况的项目,也是后端开发人员不关心执行计划的第一个项目。
  • 你也可以使用optimize for提示代替局部变量,或者使用未知的,这与使用局部变量相同,或者如果你知道一个好的值,你也可以给出它。
猜你喜欢
  • 2016-10-07
  • 2019-06-19
  • 1970-01-01
  • 2015-04-26
  • 2014-09-28
  • 1970-01-01
  • 2013-12-07
  • 1970-01-01
  • 2011-05-16
相关资源
最近更新 更多