• Entity Framework数据插入性能追踪


    写在开头:本文的评论者大多认为我这个测试不对,但是哪里不对没有谁给出一个明确的回复;对于若干纯粹谩骂的评论(似乎我说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         try
    17         {
    18             context.SaveChanges();
    19         }
    20         catch (DbEntityValidationException dbEx)
    21         { }
    22         catch
    23         { }
    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             try
    20             {
    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             catch
    33             {
    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

  • 相关阅读:
    oracle trunc()函数的用法——日期、数字
    ORACLE定时任务时间间隔设置
    Oracle JOB 间隔时间详解
    "规格"与"数量"的英文缩写是什么
    “金额”“合计”用英语怎么说?有什么区别么?
    关于狼性的团队励志名言警句
    5篇关于职场技巧的励志文章
    菜单权限分配源码奉送V2.0
    安装 SQL Server 客户端驱动程序
    一步步开发自己的博客 .NET版(9、从model first替换成code first 问题记录)
  • 原文地址:https://www.cnblogs.com/newton/p/3120497.html
Copyright © 2020-2023  润新知