简体   繁体   English

实体框架插入性能

[英]Entity Framework insertion performance

Im testing using Entity Framework with a Azure Sql db. 我使用带有Azure Sql数据库的实体框架进行即时测试。 When inserting 1 record, the action takes 400ms. 插入1条记录时,操作需要400毫秒。 When adding 20 it is 2500ms. 加20时为2500毫秒。

400ms for inserting 1 record via EF seems like a lot. 通过EF插入1条记录需要400毫秒。

What is the normal performance rate for EF? EF的正常效率是多少?

Am I doing something wrong? 难道我做错了什么?

Im aware that bulk insertion can be improved, but I thought that a single insert could be done a lot faster!? 我知道可以改进批量插入,但是我认为单次插入可以快得多!

var start = DateTime.Now;
testdbEntities testdbEntities = new testdbEntities();

for (int i = 0; i < 20; i++)
    testdbEntities.Users.Add(new User{Name = "New user"});

testdbEntities.SaveChanges();

var end = DateTime.Now;
var timeElapsed = (end - start).TotalMilliseconds;

All common tricks like: 所有常见的技巧如:

  • AutoDetectChangesEnabled = false AutoDetectChangesEnabled =否
  • Use AddRange over Add 在Add上使用AddRange
  • Etc. 等等。

Will not work like you already have noticed since the performance problem is not within Entity Framework but with SQL Azure 不会像您已经注意到的那样工作,因为性能问题不在Entity Framework中,而在SQL Azure中

SQL Azure may look pretty cool at first but it's slow as hell unless you paid for a very good Premium Database Tier. 首先,SQL Azure看起来可能很酷,但是除非您支付了非常好的Premium数据库层费用,否则它会像地狱般缓慢。

As Evk recommended, you should try to execute a simple SQL Command like "SELECT 1" and you will notice this probably take more than 100ms which is ridiculously slow. 正如Evk所建议的那样,您应该尝试执行一个简单的SQL命令,例如“ SELECT 1”,您会注意到这可能要花费100毫秒以上的时间,这太慢了。

Solution: 解:

  • Move to a better SQL Azure Tier 转向更好的SQL Azure层
  • Move away from SQL Azure 远离SQL Azure

Disclaimer : I'm the owner of the project Entity Framework Extensions 免责声明 :我是项目Entity Framework Extensions的所有者

Another solution is using this library which will batch multiple queries/bulk operations. 另一个解决方案是使用此库,该库将批处理多个查询/批量操作。 However again, even if this library is very fast, you will need a better SQL Azure Tier since it look every database round-trip take more than 200ms in your case. 但是,即使这个库非常快,您仍然需要一个更好的SQL Azure层,因为在您的情况下,每次数据库往返花费的时间都超过200毫秒。

Each insert results in a commit and causes log harden (flush to disk). 每次插入都会导致提交并导致日志变硬(刷新到磁盘)。 In case of writing in batches this may not result in one flush per insert (until log buffers full). 如果批量写入,可能不会导致每次插入都刷新一次(直到日志缓冲区已满)。 So try to batch the results somehow, for example using TVFs 因此,请尝试以某种方式批处理结果,例如使用TVF

You can disable the auto detect changes during your insert. 您可以在插入过程中禁用自动检测更改。 It can really improve performance. 它确实可以提高性能。 https://msdn.microsoft.com/en-us/data/jj556205.aspx https://msdn.microsoft.com/en-us/data/jj556205.aspx

I hope it helps :) 希望对您有所帮助:)

Most EF applications make use of persistent ignorant POCO entities and snapshot change tracking. 大多数EF应用程序都使用持久性无知POCO实体和快照更改跟踪。 This means that there is no code in the entities themselves to keep track of changes or notify the context of changes. 这意味着实体本身没有代码来跟踪更改或通知更改上下文。

When using most POCO entities the determination of how an entity has changed (and therefore which updates need to be sent to the database) is handled by the Detect Changes algorithm. 使用大多数POCO实体时,确定实体如何更改(以及哪些更新需要发送到数据库)的确定由检测更改算法处理。 Detect Changes works by detecting the differences between the current property values of the entity and the original property values that are stored in a snapshot when the entity was queried or attached. “检测更改”通过检测实体的当前属性值与查询或附加实体时存储在快照中的原始属性值之间的差异来工作。

Snapshot change detection takes a copy of every entity in the system when they are added to the Entity Framework tracking graph. 当将快照更改检测添加到Entity Framework跟踪图中时,它将获取系统中每个实体的副本。 Then as entities change each entity is compared to its snapshot to see any changes. 然后,当实体更改时,会将每个实体与其快照进行比较以查看任何更改。 This occurs by calling the DetectChanges method. 这是通过调用DetectChanges方法发生的。 Whats important to know about DetectChanges is that it has to go through all of your tracked entities each time its called, so the more stuff you have in your context the longer it takes to traverse. 关于DetectChanges,要知道的重要一点是,每次调用它时,都必须遍历所有被跟踪的实体,因此在上下文中拥有的内容越多,遍历所需的时间就越长。

What Auto Detect Changes does is plugs into events which happen on the context and calls detect changes as they occur. 自动检测更改的作用是插入上下文中发生的事件,并在发生更改时调用检测到这些更改。

Whenever you are adding a new User object, EF is internally tracking it & keeping the current state of newly added object in its snapshot. 每当您添加新的User对象时,EF都会在内部对其进行跟踪并将新添加的对象的当前状态保留在其快照中。 For bulk insert operations, EF will first insert all records into the DB & then call DetectChanges function. 对于批量插入操作,EF将首先将所有记录插入数据库,然后调用DetectChanges函数。 So execution time required for bulk insert is (time required to insert all records + time required for updating EF context). 因此,批量插入所需的执行时间为(插入所有记录所需的时间+更新EF上下文所需的时间)。

You can make your DB insertion relatively faster by disabling AutoDetectChanges . 通过禁用AutoDetectChanges可以相对更快地插入数据库。 So your code will look like, 因此您的代码看起来像

using (var context = new YourContext()) 
{ 
    try 
    { 
        context.Configuration.AutoDetectChangesEnabled = false; 

        // do your DB operations
    } 
    finally 
    { 
        context.Configuration.AutoDetectChangesEnabled = true; 
    } 
}

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

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