使用 sp_executesql 的非最佳执行计划

Posted

技术标签:

【中文标题】使用 sp_executesql 的非最佳执行计划【英文标题】:Non-optimal execution plan using sp_executesql 【发布时间】:2014-08-06 11:21:36 【问题描述】:

我在使用某些参数的 sql select 语句中遇到性能缓慢的问题,对于同一个查询,使用 sp_executesql 执行此选择的方式是内联方式的两倍。

问题是在sp_execute-way sql server 没有使用最优执行计划。尽管计划不同,但似乎在这两种情况下都正确使用了表的索引。我真的不明白为什么性能如此不同。

我的原始查询更复杂,但为了弄清楚发生了什么,我将原始查询简化为具有 3 个表和 2 个连接的选择。主要区别是在优化中使用哈希匹配,我真的不知道这是什么意思,但这是我能看到的唯一区别。

最佳计划(哈希匹配,超过 3 秒)

错误的计划(没有哈希匹配,与上面相同的索引,超过 12 秒)

    我认为我的问题不是“参数嗅探”,在我的情况下,对于所有不同的参数值,查询总是很慢,因为执行计划总是不正确的。

    OPTION (RECOMPILE) 无济于事,sp_executesql 一直运行缓慢并且内联方式需要更多时间(因为查询总是编译执行计划)

    表的统计信息已更新

    我必须使用sp_executesql 方式,因为报告服务似乎将选择封装在sp_executesql 调用中

有人知道为什么sp_executesql 会生成与内联查询不同的(错误的)执行计划吗?


编辑:查询没有使用相同的索引我猜是因为执行树不一样,sqlserver随意使用索引,附加你可以找到新的执行计划来强制使用相同的索引,性能现在甚至最糟糕的是,从 12 秒到超过 15 分钟(我已取消)在慢速查询中。我真的对更快地运行这个特定查询不感兴趣,因为我说这不是我正在处理的真正查询,我想弄清楚为什么内联查询和@之间的执行计划如此不同987654332@-查询。

sp_executesql 中是否有任何神奇的选项可以正常工作? :)

最佳

【问题讨论】:

如果您不提供任何代码、索引或执行计划,将很难回答您的问题。这可能吗? 我已附上执行计划,谢谢 它没有使用相同的索引:1 使用 IDX_EndDate_Start...,2 使用 EDX_SiteId_EndDate... 你是对的,索引不同我猜是因为执行树不同,我有力量(使用 index())选择使用相同的索引,慢查询现在甚至比之前,从 12 秒到超过 15 分钟(我已经取消了......)。我已编辑我的帖子以添加新的屏幕截图 评论而不是回答,因为我无法判断这是否是问题所在,因为您没有提供查询文本或第一次执行的参数值。 sp_executesql 将缓存一个计划,该计划将很大程度上取决于第一次执行时的参数值。这篇文章可能会有所帮助:sqlskills.com/blogs/kimberly/… 【参考方案1】:

我的理解是 sp_executesql 在第一次执行后会保留一个缓存的计划。后续查询可能使用了错误的缓存计划。您可以使用以下命令清除 ENTIRE SQL Server 过程缓存。

    DBCC FREEPROCCACHE

http://msdn.microsoft.com/en-us/library/ms174283.aspx

【讨论】:

以上是关于使用 sp_executesql 的非最佳执行计划的主要内容,如果未能解决你的问题,请参考以下文章

当使用 sp_executesql 作为过滤器时,保护 t-sql 动态代码的最佳方法是啥

Sql语句拼接(EXEC和sp_executesql的区别)

存储过程中执行动态Sql语句

存储过程中执行动态Sql语句

怎样SQL存储过程中执行动态SQL语句

运用计划缓冲的建议