我遇到了针对SQL Server 2008 R2运行的实体框架(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)的跟踪标志,但这似乎没有任何效果。
这给我留下了几个问题:
其他信息:
我还应该提一下,如果我通过服务管理控制台重新启动SQL Server服务,在使用下面的脚本启用跟踪标志4136之后,实际上似乎清除了跟踪标志......也许我应该以不同的方式这样做。 ..
DBCC TRACEON(4136,-1)
答案 0 :(得分:6)
<强> TL;博士强>
update statistics
我们有一个delete
查询,其中包含一个参数(主键),通过EF和sp_executesql
调用时需要大约7秒才能完成。手动运行查询,并将参数嵌入到sp_executesql
的第一个参数中,使查询快速运行(~0.2秒)。添加option (recompile)
也有效。当然,由于使用EF,我们无法使用这两种解决方法。
可能由于级联外键约束,长时间运行的查询的执行计划是,呃...,巨大的。当我查看SSMS中的执行计划时,我注意到在某些情况下不同步骤之间的箭头比其他情况更宽,可能表明SQL Server无法做出正确的决策。这让我想到了统计数据。我查看了执行计划中的步骤,以查看可疑步骤中涉及的表格。然后我为该表运行了update statistics Table
。然后我重新运行了错误的查询。我再次重新跑了。再一次只是为了确保。有效。我们的性能恢复正常。 (仍然比非sp_executesql
表现稍差,但嘿!)
事实证明,这只是我们开发环境中的一个问题。 (这是一个很大的问题,因为它使我们的集成测试永远存在。)在我们的生产环境中,我们有一份工作,定期更新所有统计数据。
答案 1 :(得分:5)
此时我会建议:
将ad hoc workload for optimize设置为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