【问题标题】:Why would the exact same SQL query result with a different execution plan when executed via the sp_executeSQL procedure?当通过 sp_executeSQL 过程执行时,为什么完全相同的 SQL 查询会产生不同的执行计划?
【发布时间】:2011-03-30 14:44:58
【问题描述】:

正如标题所述,我不明白为什么 sp_executeSQL 会生成与从 Sql Management Studio 运行查询完全不同的执行计划。

从 SQL management Studio 运行时,我的查询需要 3 秒,而通过 sp_executeSQL 在 management studio 中运行的查询需要 5 分钟。

我已经更新了统计数据并查看了索引,但我的脑海中仍然存在这样一个事实,即来自 sp_executeSQL 的执行计划比直接从我的管理工作室运行 sql 差得多。

所以这是我的问题:为什么以这两种不同的方式运行查询之间的执行计划会有如此大的差异?

谢谢

【问题讨论】:

  • 请注意,我已经看到关于 sp_executeSQL 过程的执行计划的其他问题。我只是没有看到关于为什么该过程生成与 Management Studio 或自定义存储过程如此不同的计划的解释。
  • 生成与自定义存储过程 (AFAIK) 完全相同的计划。对于存储过程和sp_executesql,计划是根据它看到的第一组参数的值编译的。当您的查询具有常量且计划未自动参数化时,SQL Server 有时可以使用矛盾检测来不执行计划的一部分,并且还会对这些特定值使用基数估计。

标签: sql-server tsql sql-execution-plan sp-executesql


【解决方案1】:

this

基本上, 同一过程可以有多个 [执行] 计划

【讨论】:

  • 我无法阅读您链接的整篇文章,但他做了一个陈述,这是我问题的关键:“虽然过程是一次性编译的,但每个查询都在它自己的,并且没有尝试分析执行流程。”所以基本上,因为查询是在 sp_executeSQL 中执行的,它单独优化的查询,对我来说,无论我如何提交查询,两个执行都应该具有完全相同的执行查询计划。事实并非如此。那有意义吗? (不过我会继续阅读这篇文章!)
  • 啊哈!所以无视我之前的评论。虽然单独处理各个语句,但会考虑提供的任何参数用于生成执行计划。又名参数嗅探。就我而言,虽然参数以 null 形式传递,但我有 if 条件将它们设置为 null。因为参数永远不会为空,但查询执行计划生成器假定它们将为空,所以引擎在创建执行计划时没有正确考虑逻辑。
  • TL;DR:在查询中使用 ISNULL 或 COALESCE 方法来正确分配默认值(如果为 null),而不是在查询之前使用 if 语句。
  • (希望你不介意,我想把答案归功于你,因为文章有答案,但我想在这个答案中提供更多细节,以更好地描述我遇到的场景)。谢谢!
【解决方案2】:

考虑一下。当你执行一个存储过程时,这个过程会有它自己的执行计划。当你执行一个查询语句时,它又会有自己的执行计划。现在,当使用 sp_executeSQL 时,您正在运行此存储过程以动态执行查询。所以本质上它的执行计划是 sp_executeSQL 和你的查询的组合。

【讨论】:

  • 完全理解,但是执行计划是查询的组合,每个查询都有自己的步骤。问题是查询 4 ​​是两者之间完全相同的查询文本,在 sp_executeSQL 调用和从 sql management studio 运行的 adhoc 查询之间是完全不同的
猜你喜欢
  • 1970-01-01
  • 2011-08-19
  • 1970-01-01
  • 1970-01-01
  • 2017-03-22
  • 1970-01-01
  • 2015-06-16
  • 1970-01-01
  • 2011-04-12
相关资源
最近更新 更多