24

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

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)查询提示由实体框架生成的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) 
+1

我无法回答有关EF的任何问题(对不起,从未碰过它),但我还有其他问题需要在您的问题中回答:您是否在设置跟踪标志后重新启动服务?你在数据库级设置什么参数(简单或强制 - 参见sys.databases.is_parameterization_forced)? “针对临时工作负载进行优化”的sp_configure设置是什么?不幸的是,如果我没有记错,开箱即用的EF会为N'foo'和N'blat'等参数生成两个不同的计划 - 因为它们长度不同。 – 2012-02-14 01:43:15

+0

对于延迟响应,我表示歉意,并感谢您的快速评论!我已将附加信息添加到原始帖子中。 – mindlessgoods 2012-02-15 19:16:55

+0

所以我会再次尝试你的测试(a)参数化设置为强制(b)为ad hoc工作负载设置为1和(c)两者都进行优化。 (b)很可能有助于这种情况,但(a)也可能有帮助。我会承认我没有用(a)进行过很多测试,但(b)已经帮助我尝试过每一次临时工作。 – 2012-02-15 19:24:47

回答

5

在这一点上,我会建议:


设置特设工作负载设置为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 Server配置管理器使用命令行设置跟踪标志,而不是在查询窗口中使用全局标志。见http://msdn.microsoft.com/en-us/library/ms187329.aspx

6

TL;博士

update statistics


我们有一个delete查询与花〜7秒完成通过EF和sp_executesql调用时的一个参数(主键)。手动运行查询,将参数嵌入sp_executesql的第一个参数,使查询快速运行(〜0.2秒)。加入option (recompile)也工作。当然,自从使用EF以来,这两种解决方法并不适用于我们。

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

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

+1

这可以在工作时起作用,但不会总是工作 - 仍然留下“没有好方法”从EF获取SQL Server的提示。 – user2864740 2015-02-24 02:03:29