24

我遇到了针对 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)的跟踪标志,但这似乎没有任何效果。

这给我留下了几个问题:

  1. 无论如何将 OPTION(RECOMPILE) 查询提示附加到实体框架生成的 SQL 中?
  2. 有没有办法阻止实体框架使用 exec sp_executesql,而是简单地运行原始 SQL?
  3. 还有其他人遇到这个问题吗?还有其他提示/提示吗?

附加信息:

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

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

DBCC TRACEON(4136,-1)
4

2 回答 2

8

tl;博士

update statistics


我们有一个delete带有一个参数(主键)的查询,当通过 EF 和sp_executesql. 手动运行查询,在第一个参数中嵌入参数以sp_executesql使查询快速运行(~0.2 秒)。添加option (recompile)也有效。当然,因为我们使用的是 EF,所以我们无法使用这两种解决方法。

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

It turned out that this was only a problem in our development environment. (And it was a big problem because it made our integration tests take forever.) In our production environment, we had a job running that updated all statistics on a regular basis.

于 2013-03-18T13:24:16.943 回答
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

于 2012-05-02T00:57:17.010 回答