简体   繁体   English

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

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

I'am developing a software based on Entity Framework to handle data in a MS SQL Server 2008 database. 我正在开发一个基于Entity Framework的软件来处理MS SQL Server 2008数据库中的数据。

[Trouble 1] [麻烦1]

I've just tried to insert some small data ( about 2 Mb ) from my progam to the database : the performance are very bad ! 我刚尝试从我的程序中将一些小数据( 大约2 Mb )插入到数据库中:性能非常糟糕! It takes more than 1 minute to insert these datas ! 插入这些数据需要1分钟以上

I've try to generate pre-compiled views, I've got the same results :-( 我试着生成预编译的视图,我得到了相同的结果:-(

All my code use a business layer (automatically generated from .edmx file with T4 template) to manage data in a service layer. 我的所有代码都使用业务层(使用带有T4模板的.edmx文件自动生成)来管理服务层中的数据。 It is very pratical to navigate in the relations of objects. 在对象关系中导航是非常实际的。

How can I improve the performance of these inserts with Entity Framework ? 如何使用Entity Framework提高这些插入的性能?

[Trouble 2] [麻烦2]

Also, before inserting data in database with SaveChanges() method, I fill my object context with AddObject() method. 此外,在使用SaveChanges()方法在数据库中插入数据之前,我使用AddObject()方法填充对象上下文。 I add about 100 000 small objects (about 2 Mb) to my object context with AddObject() : it takes a very long time (more than 10 minutes) ! 我使用AddObject()向我的对象上下文添加大约10万个小对象(大约2 Mb):它需要很长时间(超过10分钟)!

How can I decrease this time ? 我怎样才能减少这个时间?

UPDATE UPDATE

My program must save more than 50 Mb in database in less than 2-3 minutes ? 我的程序必须在不到2-3分钟的时间内在数据库中保存超过50 Mb的数据? Do you think it will be possible with EF ? 您认为EF可以实现吗?

You could use the Entity Framework Profiler to check what SQL is being generated. 您可以使用Entity Framework Profiler来检查正在生成的SQL。 This tool has a 30 day free trial. 此工具有30天的免费试用期。 It also claims that it can do "Analysis and detection of common pitfalls when using Entity Framework". 它还声称它可以做“分析和检测使用实体框架时常见的陷阱”。

There is also this article on EF tuning 还有关于EF调整的这篇文章

Edit 编辑

Based on your edits EF is not the way to go. 根据您的编辑,EF不是要走的路。 You need to do a bulk insert in order to get the data in that fast. 您需要进行批量插入才能快速获取数据。 Have a look at this link where I helped someone reduce load time from 10 hours to 6 mins. 看看这个链接,我帮助有人将负载时间从10小时减少到6分钟。

EF (and LINQ2SQL for that matter) does a single update/insert per record. EF(和LINQ2SQL就此而言)每条记录只进行一次更新/插入。 This usually results in less then acceptable performance for bulk inserts/updates. 这通常导致批量插入/更新的性能低于可接受的性能。 The work around is to create stored procedures, that will do these tasks for you. 解决方法是创建存储过程,为您执行这些任务。 This is an acceptable solution in most of the cases, when you do these operations on a small number of object types, in which case it is still feasable to use EF, and write those SPs manually, and then add them to the EDMX. 在大多数情况下,当您对少量对象类型执行这些操作时,这是可接受的解决方案,在这种情况下,使用EF仍然可行,并手动编写这些SP,然后将它们添加到EDMX。 You can google for using stored procedures in EF. 您可以谷歌在EF中使用存储过程。

There are several possibilities here. 这里有几种可能性。

  1. The database hardware might not be up to the task of handling 100,000 inserts. 数据库硬件可能无法完成处理100,000个插入的任务。 How many tables are involved? 涉及多少个表? Are there ancillary considerations such as triggers that are firing? 是否存在诸如触发器等辅助因素? Is the database memory constrained? 数据库内存是否受限?

  2. The Web server hardware might not be up to the task of processing that much load. Web服务器硬件可能无法承担处理这么多负载的任务。 Where is the data originating? 数据源自何处? How long is it taking to transfer to the web server? 转移到Web服务器需要多长时间? How many inserts/sec is the web server actually sending to the database server? Web服务器实际发送到数据库服务器的插入数/秒是多少?

To sum up, you have to profile to figure out exactly where the bottlenecks are. 总而言之,您必须进行分析以确定瓶颈的确切位置。 With the information you've given so far it could be anywhere. 根据您迄今为止提供的信息,它可能在任何地方。

You need to run a profiler on the web server, and you need to use SQL Profiler on the database server. 您需要在Web服务器上运行探查器,并且需要在数据库服务器上使用SQL事件探查器。 Additionally, you should be monitoring both machines CPU, memory, and network usage graphs while loading the data. 此外,您应该在加载数据时监视计算机的CPU,内存和网络使用情况图。

Once you have all of that data you should be able to pinpoint where the problem is. 获得所有这些数据后,您应该能够确定问题所在。

UPDATE UPDATE
As a side note, EF has to create at least 100,000 objects to hold the data that you are uploading (one for each record). 作为旁注,EF必须创建至少100,000个对象来保存要上载的数据(每个记录一个)。 This has it's own overhead which is why ORM's are usually not a good idea for large scale inserting/updating data. 这有它自己的开销,这就是为什么ORM通常不适合大规模插入/更新数据。

UPDATE 2 更新2
If you are running both the client and the database server on the exact same desktop machine then you are likely to have hardware issues. 如果您在完全相同的台式机上运行客户端和数据库服务器,那么您可能会遇到硬件问题。 Hopefully you have a multi-core system with at least 4 GB of ram. 希望您拥有一个至少4 GB内存的多核系统。 Everything on your system is going to be competing for resources: visual studio, SQL Server, the app itself, plus whatever else you happen to be running. 您系统上的所有内容都将争夺资源:visual studio,SQL Server,应用程序本身,以及您正在运行的任何其他内容。 Studio and SQL Server are memory and CPU hogs. Studio和SQL Server是内存和CPU占用的。 (FYI - SQL server doesn't report everything to task manager) (仅供参考 - SQL Server不向任务管理器报告所有内容)

Point is, unless you are deploying the app with an embedded sql server this isn't going to come close to being a real world test and the performance you are seeing or lack thereof has no relationship to a real world scenario. 重点是,除非您使用嵌入式SQL服务器部署应用程序,否则这不会接近真实世界的测试,您所看到或缺乏的性能与现实世界的情况无关。

As others have already pointed out more or less, Entity Framework works by sending one statement for each object and then one additional statement to fetch back ID value assigned by the database. 正如其他人已经或多或少地指出的那样,实体框架的工作原理是为每个对象发送一个语句,然后再一个语句来获取数据库分配的ID值。

This is tremendously slow when running on many objects, especially if round-trip time to the database server is anything above 1 millisecond. 在许多对象上运行时,这非常慢,特别是如果数据库服务器的往返时间超过1毫秒。

In order to improve performance when storing many objects to the database, use SqlBulkCopy class instead of Entity Framework. 为了在将许多对象存储到数据库时提高性能,请使用SqlBulkCopy类而不是Entity Framework。

You can find full comparison between Entity Framework and SqlBulkCopy in this article: How to Bulk Insert Complex Objects into SQL Server Database 您可以在本文中找到Entity Framework和SqlBulkCopy之间的完整比较: 如何将复杂对象批量插入SQL Server数据库

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

Chances are that it is not Entity Framework but your database schema that is the culprit, eg bad clustered indices or too many indices. 有可能它不是实体框架,而是您的数据库架构是罪魁祸首,例如坏的聚簇索引或太多的索引。

You can see the SQL generated by Entity Framework by using the ObjectQuery.ToTraceString property. 您可以使用ObjectQuery.ToTraceString属性查看Entity Framework生成的SQL。

If the SQL generated by Entity Framework isn't satisfactory for your needs you are able to utilize your own stored procedures for create, update and delete operations. 如果实体框架生成的SQL不能满足您的需求,您可以使用自己的存储过程进行创建,更新和删除操作。

In the original question, I get the impression that 100,000 or so objects are all created at once and a single call to SaveChanges is made. 在最初的问题中,我得到的印象是,一次创建了100,000个左右的对象,并且只进行了一次SaveChanges调用。 This kind of large unit of work where there's a single call to SaveChanges is almost always a very bad performance idea for the Entity Framework. 这种对SaveChanges进行单次调用的大型工作单元对于实体框架来说几乎总是一个非常糟糕的性能想法。 I would try dividing things up into a series of batches with maybe 100 objects or so and call SaveChanges between each batch. 我会尝试将一些批次分成大约100个对象,并在每个批次之间调用SaveChanges。 In fact I would even dispose of the context and create a new one between batches because otherwise you end up with all of those objects in the state manager at once which imposes overhead. 事实上,我甚至会处理上下文并在批处理之间创建一个新的上下文,因为否则你会立即在状态管理器中结束所有这些对象,这会产生开销。 You would probably need to experiment with different batch sizes to find the best number. 您可能需要尝试不同的批量大小才能找到最佳数量。

Also, you might want to consider what type of entities you are using. 此外,您可能想要考虑使用的实体类型。 If you use poco entities there is some overhead detecting changes which isn't present when you use classes which implement IEntityWithChangeTracking (or inherit from EntityObject which implements that interface). 如果使用poco实体,则会有一些开销检测更改,当您使用实现IEntityWithChangeTracking的类(或从实现该接口的EntityObject继承)时,这些更改不存在。

  • Danny 丹尼

I am experiencing a similar issue with my current project. 我正在遇到与我当前项目类似的问题。 I attached to SQL Profiler and kicked off my process. 我附加到SQL事件探查器并启动了我的进程。 It appears that the Entity Framework kicks off an SQL transaction for every INSERT or UPDATE each time changes are saved. 每次保存更改时,实体框架似乎都会为每个INSERT或UPDATE启动一个SQL事务。

I'm not sure if that has anything to do with the issue, but I would run SQL Profiler and examine the results. 我不确定这是否与此问题有关,但我会运行SQL事件探查器并检查结果。 I would also monitor your disk usage (reads and writes) on your SQL box (if possible) and see if there are any red flags. 我还会监视SQL框上的磁盘使用情况(读取和写入)(如果可能),看看是否有任何红色标记。

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

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