Entity Framework 4.2 exec sp_executesql不使用索引(参数嗅探)

我遇到了由对SQL Server 2008 R2运行的entity framework(4.2)生成的简单SQL查询的一些主要性能问题。 在某些情况下(但不是全部),EF使用以下语法:

exec sp_executesql 'DYNAMIC-SQL-QUERY-HERE', @param1... 

在其他情况下,只需执行提供的参数烘焙到查询中的原始SQL。 我遇到的问题是,使用sp_executesql执行的查询忽略了目标表上的所有索引,导致性能极差(通过检查SSMS中的执行计划进行确认)。

经过一番研究,听起来这个问题可能是由“参数嗅探”造成的。 如果我追加OPTION(RECOMPILE)查询提示像这样:

 exec sp_executesql 'DYNAMIC-SQL-QUERY-HERE OPTION(RECOMPILE)', @param1... 

使用目标表上的索引,查询执行速度非常快。 我也尝试切换用于禁用数据库实例( http://support.microsoft.com/kb/980653 )上的参数嗅探(4136)的跟踪标志,但是这看起来没有任何效果。

这给我留下了几个问题:

  1. 有没有办法将OPTION(RECOMPILE)查询提示附加到Entity Framework生成的SQL?
  2. 无论如何阻止Entity Framework使用exec sp_executesql,而只是运行原始SQL?
  3. 有没有人遇到这个问题? 任何其他提示/提示?

附加信息:

  1. 我没有通过SSMS重新启动数据库实例,但是,我将尝试从服务pipe理控制台重新启动服务。
  2. 参数化设置为SIMPLE(is_parameterization_forced:0)
  3. 优化特别工作负载有以下设置
    • 值:0
    • 最小值:0
    • 最大:1
    • value_in_use:0
    • is_dynamic:1
    • is_advanced:1

我还应该提到,如果我通过服务pipe理控制台在使用下面的脚本启用跟踪标志4136后重新启动SQL Server服务,似乎实际上清除跟踪标志…也许我应该这样做一个不同的方式…

 DBCC TRACEON(4136,-1) 

在这一点上,我会build议:


将ad hoc工作负载的优化设置为true。

 EXEC sp_configure 'show advanced', 1; GO RECONFIGURE WITH OVERRIDE; GO EXEC sp_configure 'optimize for ad hoc', 1; GO RECONFIGURE WITH OVERRIDE GO EXEC sp_configure 'show advanced', 0; GO RECONFIGURE WITH OVERRIDE; GO 

如果一段时间后这个设置似乎没有帮助,只有这样我才能尝试追踪标志的额外支持。 这些通常是保留作为最后的手段。 通过SQL Serverconfigurationpipe理器使用命令行来设置跟踪标志,而不是在查询窗口中使用全局标志。 请参阅http://msdn.microsoft.com/en-us/library/ms187329.aspx

TL;博士

update statistics


我们使用一个参数(主键)进行delete查询,当通过EF和sp_executesql调用时,需要大约7秒才能完成。 手动运行查询,将参数embeddedsp_executesql的第一个参数中,使查询快速运行(约0.2秒)。 添加option (recompile)也工作。 当然,自从使用EF以来,这两种解决方法并不适用于我们。

可能是由于级联外键约束,长时间运行的查询的执行计划是,呃…,巨大的。 当我看到SSMS中的执行计划时,我注意到在某些情况下,不同步骤之间的箭头比其他步骤更宽,可能表明SQL Server难以做出正确的决定。 这导致我想到统计。 我查看了执行计划中的步骤,以查看可疑步骤涉及的表格。 然后我运行该表的update statistics Table 。 然后我重新运行错误的查询。 我又重新跑了一遍。 再一次只是为了确定。 有效。 我们的performance恢复了正常。 (仍然比非sp_executesql性能差一些,但嘿!)

原来这只是我们开发环境中的一个问题。 (这是一个很大的问题,因为它使得我们的集成testing一直持续下去。)在我们的生产环境中,我们有一个工作正在运行,定期更新所有的统计数据。

Interesting Posts