Entity Framework数据插入性能追踪

来源:互联网 发布:男尊女卑的例子和数据 编辑:程序博客网 时间:2024/05/14 13:30

写在开头:本文的评论者大多认为我这个测试不对,但是哪里不对没有谁给出一个明确的回复;对于若干纯粹谩骂的评论(似乎我说EF性能低==侮辱了他全家),我已删除。我的目的就是插入7千条数据到数据库中,得出的结论是在数据Add到上下文这个阶段比较耗时,如果有能绕过这个过程的方法,或者改进的建议,请提出,否则我不认为EF在这个场景中性能低下的结论是错误的!

为了不“激怒”更多人,标题都改了好几次。当时写这篇文章并不是为了证明什么,纯粹是我在运行某项目的过程中“发现”了EF的某个瓶颈,遍寻解决方案未果,所以记录下来。唉,怪只怪我太单纯了……解决方法在文章最后。

另外关于在SaveChanges()时候会将生成的SQL语句一次性提交到数据库的言论也可以消了,后面有部分评论持这个观点,首先我一再强调瓶颈不在数据库交互阶段;为了避免类似无意义的评论反复出现,麻烦在吐槽之前用Profiler跟踪一下。

早就听说EF的性能不咋地,没想到真的不咋地,而且还不是一般的不咋地(一句玩笑话引来一群人口诛笔伐,不明真相的博主表示很淡定)。有图有真相,已经在项目中应用了EF的朋友慎入!

1、.NET4.0,EF4.4

 1 public void ExecRealTimeRun(List<RealTimeStocks> realTimeData) 2 { 3     using (var context = new StockDataEntities()) 4     { 5         context.Database.ExecuteSqlCommand("delete from RealTimeStocks"); 6  7         var now1 = DateTime.Now.TimeOfDay; 8         Console.WriteLine(string.Format("{0}开始将数据Add到上下文中,数据量:{1}", now1, realTimeData.Count)); 9         foreach (var data in realTimeData)10         {11             context.RealTimeStocks.Add(data);12         }13 14         var now2 = DateTime.Now.TimeOfDay;15         Console.WriteLine(string.Format("{0}数据Added完毕,开始执行Insert操作,耗时{1}", now2, now2 - now1));16         try17         {18             context.SaveChanges();19         }20         catch (DbEntityValidationException dbEx)21         { }22         catch23         { }24 25         var now3 = DateTime.Now.TimeOfDay;26         Console.WriteLine(string.Format("{0}Insert完毕,耗时{1}", now3, now3 - now2));27     }28 }

很简单,木有多余逻辑,结果:

插入7K多数据,超过1分钟。反复测了几次,结果相差不大,假如将SaveChanges操作包裹在TransactionScope中(纯粹为了测试,看是不是更耗时),结果没什么变化。

2、.NET4.5,EF4.4

听说只要升级到.NET4.5,EF就会有性能上的提升,因为EF用到了.NET框架的某些类库,随着这些类库的升级,EF也提高了性能。so,干巴爹。结果:

(这图可以不用贴,因为和上图没什么两样)

3、.NET4.5,EF5.0

微软跟我说5.0有67%的性能提升(有人说只是提高了查询性能,这里侧重调侃),我想这么大公司会乱说?于是卸载了4.4,安装了5.0(貌似NuGet里,会根据你的.NET版本安装相应版本的EF;但是你.NET升级后,EF不会跟着升级,也不能直接更新)。重新启动测试,结果:

(这图可以不用贴,因为和上图没什么两样)

4、其实么,关键不是在数据库插入阶段,而是在代码层的Add阶段,so,我并不认为和ADO.NET相比较有什么意义,因为ADO.NET没有上下文,而低效点就是Add到上下文的过程(博主在这里明确表示,以下代码是为了比较SaveChanges方法和ADO.NET的执行效率,而非整个插入阶段的效率)有朋友评论说我Add的方式错了,不知道应该怎么写,请教。

无论如何,贴代码吧:

 1 public void ExecRealTimeRunByADO(List<RealTimeStocks> realTimeData) 2 { 3     string insertText = @"insert [dbo].[RealTimeStocks]([Hqgpdm], [Hqzrsp], [Hqjrkp], [Hqzjcj], [Hqcjsl], [Hqdqcjsl], 4 [Hqcjje], [Hqdqcjje], [Hqcjbs], [Hqzgcj], [Hqzdcj], [Hqsyl1], [Hqsyl2], [Hqjgsd1], [Hqjgsd2], [Hqhycc], [Hqsjw5], [Hqssl5],  5 [Hqsjw4], [Hqssl4], [Hqsjw3], [Hqssl3], [Hqsjw2], [Hqssl2], [Hqsjw1], [Hqssl1], [Hqbjw1], [Hqbsl1], [Hqbjw2], [Hqbsl2],  6 [Hqbjw3], [Hqbsl3], [Hqbjw4], [Hqbsl4], [Hqbjw5], [Hqbsl5], [HQTime], [UpdateTime], [ExponentRiseDown], [RiseDownPercent],  7 [ExponentSwing], [TimeID], [RiseNum], [DownNum], [EqualNum], [DataSource], [IsDeleted], [AddTime], [SMGUID]) 8 values ('{0}', {1}, {2}, {3}, {4}, null, {5}, null, null, {6}, {7}, {8}, null, {9}, {10}, null, {11}, {12}, {13}, {14}, {15},  9 {16}, {17}, {18}, null, {19}, null, {20}, {21}, {22}, {23}, {24}, {25}, {26}, {27}, {28}, '{29}', '{30}', {31}, {32}, {33}, {34},10 {35}, {36}, {37}, null, {38}, '{39}', '{40}')";11     using (var context = new StockDataEntities())12     {13         context.Database.ExecuteSqlCommand("delete from RealTimeStocks");14 15         var now2 = DateTime.Now.TimeOfDay;16         Console.WriteLine(string.Format("{0}开始执行Insert操作", now2));17         using (TransactionScope scope = new TransactionScope(TransactionScopeOption.RequiresNew, new TimeSpan(0, 2, 0)))18         {19             try20             {21                 foreach (var data in realTimeData)22                 {23                     string cmd = string.Format(insertText, data.Hqgpdm, data.Hqzrsp, data.Hqjrkp, data.Hqzjcj, data.Hqcjsl,24 data.Hqcjje, data.Hqzgcj, data.Hqzdcj, data.Hqsyl1, data.Hqjgsd1, data.Hqjgsd2, data.Hqsjw5, data.Hqssl5,25 data.Hqsjw4, data.Hqssl4, data.Hqsjw3, data.Hqssl3, data.Hqsjw2, data.Hqssl2, data.Hqssl1, data.Hqbsl1, data.Hqbjw2, data.Hqbsl2,26 data.Hqbjw3, data.Hqbsl3, data.Hqbjw4, data.Hqbsl4, data.Hqbjw5, data.Hqbsl5, data.HQTime, data.UpdateTime, data.ExponentRiseDown, data.RiseDownPercent,27 data.ExponentSwing, data.TimeID, data.RiseNum, data.DownNum, data.EqualNum, data.IsDeleted ? 1 : 0, data.AddTime, data.SMGUID);28                     context.Database.ExecuteSqlCommand(cmd);29                 }30                 scope.Complete();31             }32             catch33             {34                 Console.WriteLine("出错");35                 return;36             }37 38             var now3 = DateTime.Now.TimeOfDay;39             Console.WriteLine(string.Format("{0}Insert完毕,耗时{1}", now3, now3 - now2));40         }41     }42 }

Insert语句我是直接拷贝EF动态生成的语句,稍微修改了下。使用的虽然不是正宗的ADO.NET,但是也差不多,你别跟我说EF的ExecuteSqlCommand用的是另一套东西。

结果:

不言自明(看来还有些人不明白,博主想说:SaveChanges并没有多少性能损失)。

结论:坐等10.0版本!or context.Configuration.AutoDetectChangesEnabled = false!(thx to eflay && flytothemoon)

转载请注明本文出处:http://www.cnblogs.com/newton/archive/2013/06/06/3120497.html


<script type="text/javascript"><!--google_ad_client = "ca-pub-1944176156128447";/* cnblogs 首页横幅 */google_ad_slot = "5419468456";google_ad_width = 728;google_ad_height = 90;//--></script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
原创粉丝点击