繁体   English   中英

实体框架4:SQL Server 2008的性能不佳

[英]Entity Framework 4 : Bad performance with SQL Server 2008

我正在开发一个基于Entity Framework的软件来处理MS SQL Server 2008数据库中的数据。

[麻烦1]

我刚尝试从我的程序中将一些小数据( 大约2 Mb )插入到数据库中:性能非常糟糕! 插入这些数据需要1分钟以上

我试着生成预编译的视图,我得到了相同的结果:-(

我的所有代码都使用业务层(使用带有T4模板的.edmx文件自动生成)来管理服务层中的数据。 在对象关系中导航是非常实际的。

如何使用Entity Framework提高这些插入的性能?

[麻烦2]

此外,在使用SaveChanges()方法在数据库中插入数据之前,我使用AddObject()方法填充对象上下文。 我使用AddObject()向我的对象上下文添加大约10万个小对象(大约2 Mb):它需要很长时间(超过10分钟)!

我怎样才能减少这个时间?

UPDATE

我的程序必须在不到2-3分钟的时间内在数据库中保存超过50 Mb的数据? 您认为EF可以实现吗?

您可以使用Entity Framework Profiler来检查正在生成的SQL。 此工具有30天的免费试用期。 它还声称它可以做“分析和检测使用实体框架时常见的陷阱”。

还有关于EF调整的这篇文章

编辑

根据您的编辑,EF不是要走的路。 您需要进行批量插入才能快速获取数据。 看看这个链接,我帮助有人将负载时间从10小时减少到6分钟。

EF(和LINQ2SQL就此而言)每条记录只进行一次更新/插入。 这通常导致批量插入/更新的性能低于可接受的性能。 解决方法是创建存储过程,为您执行这些任务。 在大多数情况下,当您对少量对象类型执行这些操作时,这是可接受的解决方案,在这种情况下,使用EF仍然可行,并手动编写这些SP,然后将它们添加到EDMX。 您可以谷歌在EF中使用存储过程。

这里有几种可能性。

  1. 数据库硬件可能无法完成处理100,000个插入的任务。 涉及多少个表? 是否存在诸如触发器等辅助因素? 数据库内存是否受限?

  2. Web服务器硬件可能无法承担处理这么多负载的任务。 数据源自何处? 转移到Web服务器需要多长时间? Web服务器实际发送到数据库服务器的插入数/秒是多少?

总而言之,您必须进行分析以确定瓶颈的确切位置。 根据您迄今为止提供的信息,它可能在任何地方。

您需要在Web服务器上运行探查器,并且需要在数据库服务器上使用SQL事件探查器。 此外,您应该在加载数据时监视计算机的CPU,内存和网络使用情况图。

获得所有这些数据后,您应该能够确定问题所在。

UPDATE
作为旁注,EF必须创建至少100,000个对象来保存要上载的数据(每个记录一个)。 这有它自己的开销,这就是为什么ORM通常不适合大规模插入/更新数据。

更新2
如果您在完全相同的台式机上运行客户端和数据库服务器,那么您可能会遇到硬件问题。 希望您拥有一个至少4 GB内存的多核系统。 您系统上的所有内容都将争夺资源:visual studio,SQL Server,应用程序本身,以及您正在运行的任何其他内容。 Studio和SQL Server是内存和CPU占用的。 (仅供参考 - SQL Server不向任务管理器报告所有内容)

重点是,除非您使用嵌入式SQL服务器部署应用程序,否则这不会接近真实世界的测试,您所看到或缺乏的性能与现实世界的情况无关。

正如其他人已经或多或少地指出的那样,实体框架的工作原理是为每个对象发送一个语句,然后再一个语句来获取数据库分配的ID值。

在许多对象上运行时,这非常慢,特别是如果数据库服务器的往返时间超过1毫秒。

为了在将许多对象存储到数据库时提高性能,请使用SqlBulkCopy类而不是Entity Framework。

您可以在本文中找到Entity Framework和SqlBulkCopy之间的完整比较: 如何将复杂对象批量插入SQL Server数据库

您可以使用SQL Server Profiler对查询进行概要分析,然后使用数据库引擎优化顾问来确定要添加的更好的统计信息和索引。

有可能它不是实体框架,而是您的数据库架构是罪魁祸首,例如坏的聚簇索引或太多的索引。

您可以使用ObjectQuery.ToTraceString属性查看Entity Framework生成的SQL。

如果实体框架生成的SQL不能满足您的需求,您可以使用自己的存储过程进行创建,更新和删除操作。

在最初的问题中,我得到的印象是,一次创建了100,000个左右的对象,并且只进行了一次SaveChanges调用。 这种对SaveChanges进行单次调用的大型工作单元对于实体框架来说几乎总是一个非常糟糕的性能想法。 我会尝试将一些批次分成大约100个对象,并在每个批次之间调用SaveChanges。 事实上,我甚至会处理上下文并在批处理之间创建一个新的上下文,因为否则你会立即在状态管理器中结束所有这些对象,这会产生开销。 您可能需要尝试不同的批量大小才能找到最佳数量。

此外,您可能想要考虑使用的实体类型。 如果使用poco实体,则会有一些开销检测更改,当您使用实现IEntityWithChangeTracking的类(或从实现该接口的EntityObject继承)时,这些更改不存在。

  • 丹尼

我正在遇到与我当前项目类似的问题。 我附加到SQL事件探查器并启动了我的进程。 每次保存更改时,实体框架似乎都会为每个INSERT或UPDATE启动一个SQL事务。

我不确定这是否与此问题有关,但我会运行SQL事件探查器并检查结果。 我还会监视SQL框上的磁盘使用情况(读取和写入)(如果可能),看看是否有任何红色标记。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM