【发布时间】:2018-12-28 11:14:13
【问题描述】:
我在 ASP.NET MVC5 中运行 EF6 (v6.2.0)。
当通过 EF6 的 SqlQuery() 函数执行某个 StoredProcedure 时,我必须等待大约 2 分钟(!)才能在内存中获取结果。
由于一些复杂的计算,StoredProcedure 在数据库中需要大约 9 - 12 秒,并使用 11 个参数调用:
exec sp_Calculation @q, @y, @gn, @gesa, @rg, @cl, @yc, @vlv, @vlb, @ugv, @ugb
结果是大约 2.1 MB 的数据(~9000 行,49 列)。
总执行时间:00:00:11.711
在代码中我这样称呼它:
dbContext.Database.Log = s => Trace.Write(s);
return await dbContext.Database.SqlQuery<CalculationResult>("exec sp_Calculation @q, @y, @gn, @gesa, @rg, @cl, @yc, @vlv, @vlb, @ugv, @ugb", parameters).ToListAsync(token);
追踪:
exec sp_Calculation @q, @y, @gn, @gesa, @rg, @cl, @yc, @vlv, @vlb, @ugv, @ugb
-- @q: 'null' (Type = Int32, IsNullable = false)
-- @y: '1101' (Type = Int16, IsNullable = false)
-- @gn: 'null' (Type = Int32, IsNullable = false)
-- @gesa: '1' (Type = Byte, IsNullable = false)
-- @rg: 'null' (Type = Int32, IsNullable = false)
-- @cl: '4' (Type = Byte, IsNullable = false)
-- @yc: '17' (Type = Int16, IsNullable = false)
-- @vlv: 'null' (Type = Int16, IsNullable = false)
-- @vlb: 'null' (Type = Int16, IsNullable = false)
-- @ugv: 'null' (Type = Int16, IsNullable = false)
-- @ugb: 'null' (Type = Int16, IsNullable = false)
-- Executing asynchronously at 19.07.2018 18:27:23 +02:00
-- Completed in 114479 ms with result: SqlDataReader
我的第一个猜测是网络是瓶颈,但是通过 SSMS 调用 Web 服务器上的 StoredProc 也非常快。所以网络应该不是问题。
这是来自 dotTrace 的调用堆栈,其中存在很大瓶颈: 奇怪的是原生程序集的执行时间非常长。
有人可以澄清那里到底发生了什么以及如何解决这个问题吗?
编辑: 我刚刚找到了一个有类似问题的question,并将尝试了解更多有关它的信息。也许它是网络。
编辑 2:
由于在从中创建 csv 文件之前进行了一些预处理,我确实需要内存中的所有数据。瓶颈似乎在SNINativeMethodWrapper。我不需要帮助就可以使用其他库执行我的任务。我只是想在内存中更快地获取数据。
【问题讨论】:
-
ORM 不适用于报告查询。等待 9K 行返回,将它们转换为列表并然后使用它们也很慢,并且可能会导致大量重新分配。使用 IEnumerable 开始处理结果。毕竟,对于报告或导出,您不需要所有数据,您可以在第一行到达后立即开始写出结果。
-
你也可以使用像 Dapper 这样的 microORM。由于您不处理实体,因此您不需要更改跟踪、更新支持以及完整 ORM 提供的所有其他功能。只是将 DbDataReader 行映射到 CalculationResult 对象
-
我们在整个应用程序中使用 EF6 并且几乎使用了它的所有功能。所以现在换掉不是一个选择。问题是,加载数据后会有更多的处理。但是单独加载需要很长时间。 EF6 在显示 Trace 所用时间时是否考虑了对象分配?
-
这不是使用错误功能的理由。 SO也使用EF。和小巧玲珑。我认为 ADO.NET 也是必要的。 ORM仍然不适合报告导出查询
-
plain ADO.NET 给了我相同的结果,因此 EF6 本身没有问题。一些本地的东西似乎很疯狂,但我需要知道那里到底出了什么问题。
标签: c# sql-server performance entity-framework-6