【发布时间】:2014-12-03 16:13:43
【问题描述】:
所以我一直在分析这个 MVC 应用程序,我注意到某些查询很慢,所以我自然而然地分析了我的应用程序和数据库。
这些是调查结果:
对于 29 个 SQL 命令,根据 MSSQL 分析器,所有 DB 调用的总和为 48ms。 这似乎是合理的。
编辑:这 29 个调用中的每一个都跟随着 exec sp_reset_connection 命令(不确定是否相关)。
这是奇怪的部分,应用程序分析是这样说的:
实体框架的
internal virtual DbDataReader ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior)
用了 578ms 来执行。或者让我进一步分解。
private ObjectResult<T> GetResults(MergeOption? forMergeOption)
{
this.QueryState.ObjectContext.AsyncMonitor.EnsureNotEntered();
IDbExecutionStrategy executionStrategy = DbProviderServices.GetExecutionStrategy(this.QueryState.ObjectContext.Connection, this.QueryState.ObjectContext.MetadataWorkspace);
if (executionStrategy.RetriesOnFailure && this.QueryState.EffectiveStreamingBehaviour)
throw new InvalidOperationException(Strings.ExecutionStrategy_StreamingNotSupported((object) executionStrategy.GetType().Name));
else
return executionStrategy.Execute<ObjectResult<T>>((Func<ObjectResult<T>>) (() => this.QueryState.ObjectContext.ExecuteInTransaction<ObjectResult<T>>((Func<ObjectResult<T>>) (() => this.QueryState.GetExecutionPlan(forMergeOption).Execute<T>(this.QueryState.ObjectContext, this.QueryState.Parameters)), executionStrategy, false, !this.QueryState.EffectiveStreamingBehaviour)));
}
在 578 毫秒中需要 552 毫秒。
如果我进一步分解它。
public ObjectResult<T> Execute(MergeOption mergeOption)
{
EntityUtil.CheckArgumentMergeOption(mergeOption);
return this.GetResults(new MergeOption?(mergeOption));
}
397 毫秒
GetEnumerator 需要 155ms,该方法调用 Lazy 方法“CreateValue”等...
我会在这里停下来。
这些执行时间由 Jetbrains DotTrace 测量。
我确实意识到拥有 EF 本质上意味着“一些”开销。但这似乎太过分了。
EF 6.1.2, SQL Server 2012 标准版
我要求太多了吗?当期望“一些”开销而不是 12 倍开销时,我是否不合理?
或者我只是没有以正确的方式解决这个问题?
最好的问候, T.
【问题讨论】:
-
嗯,你是在比较苹果和橙子。实体框架确实在查询数据库之外工作。它必须实例化对象,设置所有关系,初始化所有对象跟踪的东西。这些都不便宜,当涉及 29 个查询时,我认为 500 毫秒并不是那么糟糕。对于单个页面加载,这是相当多的查询。是的,任何 ORM 都会有开销。如果您的问题是 EF 的效率如何,那么您需要使用其他 ORM 选项进行分析,而不是针对直接 SQL。
-
嗨,克里斯。我实际上并没有比较它,我只是对查询和执行它们所需的完整 EF 操作之间的差异幅度感到惊讶。就像我提到的那样,开销是预期的,因为“开销”用于创建应用程序对象等,就像你说的那样。我会将这些查询合并到更简单的视图或存储过程中,然后返回结果。
-
实际上,您没有提到您的测试是如何构建的。 48ms 是否仅用于传输时间中的 SQL 因素?请记住,到数据库的往返需要一些时间,并且取决于所涉及的网络延迟,发送查询需要 100-200 毫秒,而接收结果需要另外 100-200 毫秒,这不会是异常的。如果是这种情况,那么您只看到 EF 大约 200 毫秒的处理时间,这仅比直接 SQL 增加了 4 倍。
-
我认为网络或拓扑不是问题。这是在开发机器上的测试。一切都是本地的。
-
好的,但这会使事情向相反的方向倾斜。本地开发分析几乎毫无用处,因为您的桌面类开发机器无法匹配实际的 Web 服务器,而且 IIS Express 是单线程的且未经过优化。真正的 IIS 将能够运行得更快,尤其是在服务器硬件上。开发分析仅用于确保在任何地方都没有巨大的异常瓶颈。否则,请将您的配置文件保存为您的生产服务器或其传真,例如 stage 或 QA。
标签: c# sql-server entity-framework asp.net-mvc-4 entity-framework-6