实体框架4.2 exec sp_executesql不使用索引(参数嗅探)

min*_*ods 24 entity-framework parameter-sniffing sql-server-2008-r2 sp-executesql

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

exec sp_executesql 'DYNAMIC-SQL-QUERY-HERE', @param1...
Run Code Online (Sandbox Code Playgroud)

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

经过一些研究,听起来这个问题可能是由"参数嗅探"造成的.如果我附加OPTION(RECOMPILE)查询提示,如下所示:

exec sp_executesql 'DYNAMIC-SQL-QUERY-HERE OPTION(RECOMPILE)', @param1...
Run Code Online (Sandbox Code Playgroud)

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

这给我留下了一些问题:

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

附加信息:

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

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

DBCC TRACEON(4136,-1)
Run Code Online (Sandbox Code Playgroud)

Chr*_*tte 8

TL;博士

update statistics


我们有一个delete查询带有一个参数(主键),通过EF和调用时需要大约7秒才能完成sp_executesql.手动运行查询,使用第一个参数中嵌入的参数sp_executesql使查询快速运行(~0.2秒).添加option (recompile)也有效.当然,由于使用EF,我们无法使用这两种解决方法.

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

事实证明,这只是我们开发环境中的一个问题.(这是一个很大的问题,因为它使我们的集成测试永远存在.)在我们的生产环境中,我们有一个运行的工作,定期更新所有统计数据.


Aar*_*and 5

此时我会建议:


将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
Run Code Online (Sandbox Code Playgroud)

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