轉自https://www.cnblogs.com/yaopengfei/p/7751545.html
一. 綜述
該模塊主要介紹:EF的性能優化插件Z.EntityFramework.Extensions,該插件收費。
(一). 簡介
1. 相關網站:http://www.zzzprojects.com/
2. 下載途徑:通過Nuget直接下載或者去官網下載(要注意更新最新版本,可能會過期)
3. 該程序集包括三個核心模塊:Bulk SaveChanges、Bulk Operations、Batch Operations
(二).Bulk SaveChanges 大批量保存
1. 核心方法:BulkSaveChanges
2. 該方法是在EF原有方法SaveChanges方法上的一個提升。
3. 使用方法:增刪改操作均使用EF自有的方式,最后事務性提交數據庫,BulkSaveChanges代替SaveChanges
4. 工作原理:與SaveChanges類似,但是減少了與數據庫的往返次數,從而提高了性能
5. 性能測試:以增加數據為例進行測試:
1000條 5000條 10000條
1.606s 6.542s 21.857s
6. 可配置參數 (改變這兩個參數對性能影響不大)
①.BatchSize 批量提交塊的大小
②.AllowConcurrency 是否允許並發檢查
(三). Bulk Operations
1. 核心方法:BulkInsert(增加)、BulkDelete(刪除)、BulkUpdate(修改)、BulkMerge(合並)、BulkSynchronize(同步)
其中:BulkMerge(合並)、BulkSynchronize(同步)不常用,這里不單獨測試了。 (根據傳入的類型可以直接找到對應的表進行操作)
2. 工作原理:盡可能的減少與數據庫的往返次數,
3. 性能測試:BulkInsert性能進行測試:
1000條 5000條 10000條 40000條
1.432s 1.568s 1.554s 1.899s
4. 性能測試:BulkDelete性能進行測試:
1000條 5000條 10000條 40000條
1.430s 1.542s 1.540s 2.597s
5. 可配置參數 (改變這兩個參數對性能影響不大)
①.BatchSize 批量提交塊的大小
②.AllowConcurrency 是否允許並發檢查
(四). Batch Operations (批量進行統一操作)
1. 核心方法:DeleteFromQuery、UpdateFromQuery
2. 使用方法:
①. context.Customers.Where(x => x.ID == userId).DeleteFromQuery();
②. context.Customers.Where(x => x.ID == userId).UpdateFromQuery(x => new Customer {Actif = false});
3. 性能測試: DeleteFromQuery的性能測試
1000條 5000條 10000條 40000條
0.1s 0.127s 0.156s 0.490s
4. 性能測試: UpdateFromQuery的性能測試
1000條 5000條 10000條 40000條
0.120s 0.131s 0.172s 0.437s
二. 代碼實戰
1. 1.以增加數據為例,進行測試BulkSaveChanges(測試數據條數:1000,5000,10000)
1 private static void NewMethod1(DbContext db, int count) 2 { 3 Console.WriteLine("-------------1. 提供BulkSaveChanges方法來替代EF本身的Savechanges------------------"); 4 Stopwatch watch = Stopwatch.StartNew(); 5 for (int i = 0; i < count; i++) 6 { 7 TestTwo t = new TestTwo(); 8 t.id = Guid.NewGuid().ToString("N"); 9 t.t21 = "t1+" + i; 10 t.t22 = "t2+" + i; 11 db.Set<TestTwo>().Add(t); 12 } 13 14 db.BulkSaveChanges(); 15 16 //db.BulkSaveChanges(options => 17 //{ 18 // options.BatchSize = 1000; 19 // options.AllowConcurrency = false; 20 //}); 21 watch.Stop(); 22 Console.WriteLine("{0}條數據耗時:{1}", count, watch.ElapsedMilliseconds); 23 }
2. 以增加為例,測試BulkInsert方法(測試數據條數:1000,5000,1w,4w)
1 private static void NewMethod2(DbContext db, int count) 2 { 3 Console.WriteLine("-------------1. 以增加為例,測試BulkInsert方法(測試數據條數:1000,5000,1w,4w)------------------"); 4 Stopwatch watch = Stopwatch.StartNew(); 5 List<TestTwo> list = new List<TestTwo>(); 6 for (int i = 0; i < count; i++) 7 { 8 TestTwo t = new TestTwo(); 9 t.id = Guid.NewGuid().ToString("N"); 10 t.t21 = "t1+" + i; 11 t.t22 = "t2+" + i; 12 list.Add(t); 13 } 14 15 db.BulkInsert(list); 16 17 //db.BulkInsert(list, p => 18 //{ 19 // p.BatchSize = 100; 20 // p.AllowConcurrency = false; 21 //}); 22 watch.Stop(); 23 Console.WriteLine("{0}條數據耗時:{1}", count, watch.ElapsedMilliseconds); 24 }
3. 以刪除為例,測試BulkDelete方法(測試數據條數:1000,5000,1w,4w)
1 private static void NewMethod3(DbContext db, int count) 2 { 3 Console.WriteLine("-------------2. 以刪除為例,測試BulkDelete方法(測試數據條數:1000,5000,1w,4w)------------------"); 4 Stopwatch watch = Stopwatch.StartNew(); 5 List<TestTwo> list = db.Set<TestTwo>().Take(count).ToList(); 6 db.BulkDelete(list); 7 watch.Stop(); 8 Console.WriteLine("{0}條數據耗時:{1}", count, watch.ElapsedMilliseconds); 9 }
4. DeleteFromQuery的性能測試(測試數據條數:1000,5000,1w,4w)
1 private static void NewMethod4(DbContext db, int count) 2 { 3 Console.WriteLine("-------------1. DeleteFromQuery的性能測試(測試數據條數:1000,5000,1w,4w)------------------"); 4 Stopwatch watch = Stopwatch.StartNew(); 5 db.Set<TestTwo>().Where(u=>u.id!="fk").DeleteFromQuery(); 6 7 watch.Stop(); 8 Console.WriteLine("{0}條數據耗時:{1}", count, watch.ElapsedMilliseconds); 9 }
5. UpdateFromQuery的性能測試(測試數據條數:1000,5000,1w,4w)
1 private static void NewMethod5(DbContext db, int count) 2 { 3 Console.WriteLine("-------------2. UpdateFromQuery的性能測試(測試數據條數:1000,5000,1w,4w)------------------"); 4 Stopwatch watch = Stopwatch.StartNew(); 5 db.Set<TestTwo>().Where(u => u.id != "fk").UpdateFromQuery(x => new TestTwo { 6 t21="1", 7 t22="2" 8 }); 9 10 watch.Stop(); 11 Console.WriteLine("{0}條數據耗時:{1}", count, watch.ElapsedMilliseconds); 12 }