我遇到了针对 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...
使用目标表上的索引并且查询执行得非常快。我还尝试切换用于禁用数据库实例上的参数嗅探(4136)的跟踪标志(http://support.microsoft.com/kb/980653 http://support.microsoft.com/kb/980653),但这似乎没有任何效果。
这给我留下了几个问题:
- 是否有办法将 OPTION(RECOMPILE) 查询提示附加到实体框架生成的 SQL 中?
- 是否有办法阻止实体框架使用 exec sp_executesql,而只是运行原始 SQL?
- 还有其他人遇到这个问题吗?还有其他提示/技巧吗?
附加信息:
- 我确实通过 SSMS 重新启动了数据库实例,但是,我将尝试从服务管理控制台重新启动服务。
- 参数化设置为 SIMPLE(is_parameterization_forced:0)
- Optimize for adhoc workloads has the following settings
- value: 0
- 最小值:0
- 最大值:1
- 使用价值:0
- 动态:1
- 是_高级:1
我还应该提到,如果我在使用下面的脚本启用跟踪标志 4136 后通过服务管理控制台重新启动 SQL Server 服务,似乎实际上清除了跟踪标志...也许我应该以不同的方式执行此操作...
DBCC TRACEON(4136,-1)
tl;dr
update statistics
我们有一个delete
通过 EF 调用时,使用一个参数(主键)的查询大约需要 7 秒才能完成sp_executesql
。手动运行查询,并将参数嵌入到第一个参数中sp_executesql
使查询快速运行(~0.2 秒)。添加option (recompile)
也工作过。当然,由于我们使用的是 EF,所以这两种解决方法对我们来说不可用。
可能由于级联外键约束,长时间运行的查询的执行计划非常庞大。当我查看 SSMS 中的执行计划时,我注意到在某些情况下不同步骤之间的箭头比其他步骤更宽,这可能表明 SQL Server 无法做出正确的决策。这让我开始思考统计学。我查看了执行计划中的步骤,看看可疑步骤涉及哪些表。然后我跑了update statistics Table
对于那张桌子。然后我重新运行了错误的查询。我又重新运行了一次。再次确认。有效。我们的表现恢复正常。 (还是比非差一些sp_executesql
性能,但是嘿!)
事实证明这只是我们开发环境的问题。 (这是一个大问题,因为它使我们的集成测试花费了很长时间。)在我们的生产环境中,我们运行了一个定期更新所有统计数据的作业。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)