首页 > 解决方案 > 带有 MySQL 的实体框架:ToList() 非常慢

问题描述

我将我的 Java 应用程序移植到 C# 并发现实体框架在实例化对象时似乎真的很慢。

首先,关于正在使用的版本的一些细节:

由于我正在移植我的应用程序,因此我使用了 DB First 方法。

现在,我有一个包含大约 2000 个条目的表,完全独立,没有什么特别之处。在 Java 中,我手动读取表格并实例化类,这需要大约 30 毫秒 - 仍然非常慢,但足够好。在 EF 中,这需要一秒钟...

有问题的行是:

// _baat2db is my DBContext
_baatc2db.dbexchanges.ToList();

这条线总是需要一秒钟才能完成。

使用 Interceptors,我记录了生成的 SQL:

SELECT
`Extent1`.`exchangeId`, 
`Extent1`.`mic`, 
`Extent1`.`country`, 
`Extent1`.`city`, 
`Extent1`.`timeZoneId`, 
`Extent1`.`countryIsoCode`, 
`Extent1`.`operatingMic`, 
`Extent1`.`institution`, 
`Extent1`.`acronym`, 
`Extent1`.`website`, 
`Extent1`.`statusDate`, 
`Extent1`.`creationDate`, 
`Extent1`.`comment`, 
`Extent1`.`isOperating`, 
`Extent1`.`isActive`, 
`Extent1`.`calendarId`
FROM `dbexchange` AS `Extent1`
-- Executing at 27.05.2020 14:16:42 +02:00
-- Completed in 3 ms with result: EFMySqlDataReader

所以读取表数据需要 3ms,这是人们所期望的。这也使我得出这样的结论,即花费这么长时间与数据库或数据库连接无关,而是在处理返回的数据的过程中,可能是在实例化对象时。

表字段及其映射是INT -> int和。一个是,两个具有在生成的构造函数中设置的默认值。VARCHAR -> stringBIT -> boolNullable

有什么想法吗?有什么我应该看的吗?我该怎么做才能进一步调试问题?

谢谢!


更新:

正如D Stanley 所建议的那样,它在第二次调用时表现良好(20-25ms)。

仍然很难理解为什么第一次需要 1 秒的时间,因为我之前打开了连接。例如以下测试:

_baatc2db.Database.Connection.Open();

// now, after after StateChange to ConnectionState.Open:

Thread.Sleep(5000);
_baatc2db.dbexchanges.ToList(); // 1+ second

Thread.Sleep(5000);
_baatc2db.dbexchanges.ToList(); // 20-25ms

标签: c#.netentity-framework-6

解决方案


正如 D Stanley 建议的那样,它在第二次调用时表现良好(20-25ms)。仍然很难理解为什么 [...]

您正在将此与 Java 进行比较,所以我假设您有使用它的经验。

与 C# 的最大区别在于,它在运行时实际上将代码编译为本机代码,这是一个非常重要的步骤。并且 EF 在其之上添加了额外的代码块,因为它编译您发送到 ILASM 的表达式,然后编译为本机代码,这是双倍昂贵的。

好处是,一旦编译完成,它的运行速度将与本机代码一样快——事实上甚至更好,因为 JIT 可以利用运行它的机器来发出其他机器可能不支持的汇编指令(AVX、SSE , ETC)。


推荐阅读