之前做項目的時候。做出來的系統的性能不太好,在框架中使用了EntityFramework,於是就在網上查資料,研究怎樣提高EF的性能。
在這分享一篇博客 批量操作提升EntityFramework的性能
里面提供了一個擴展庫Entity Framework擴展庫,在這里面找到了一些比較好的方法。以下主要介紹當中的一個方法—-批量加入BulkInsert。
這些擴展方法在哪里找?
在VS中新建EF之后,右鍵解決方式下的引用
, 選擇管理NuGet程序包
,搜索Z.EntityFramework.Extensions
並安裝。
然后在類里面加入引用之后就能夠直接點出來。
批量加入和EF本身自帶的加入性能提高了多少?
以下咱們就用實例說話:
構造一個10W個studentinfo實例:
'''定義要加入數據的條數'''
int customerCount = 100000;
'''定義一個實體集合'''
List<studentInfo> customers = new List<studentInfo>();
'''想集合中加入數據'''
for (int i = 0; i < customerCount; i++)
{
studentInfo customer = new studentInfo()
{
name = "2" + i,
sex = "2" + i,
studentID = "2" + i,
age = "2"
};
customers.Add(customer);
Console.Write(".");
}
用EF自帶的加入方法將數據加入到數據庫中,為了計算使用時間,加上StopWatch:
'''開始計時'''
Stopwatch watch = Stopwatch.StartNew();
using (EFTestEntities dbcontext = new EFTestEntities())
{
foreach (var entity in customers)
{
dbcontext.studentInfoes.Add(entity);
}
dbcontext.SaveChanges();
}
'''計時結束'''
watch.Stop();
'''輸出時間'''
Console.WriteLine(string.Format("{0} customers are created, cost {1} milliseconds.", customerCount, watch.ElapsedMilliseconds));
好了如今執行。等待中……
哎~~實在是沒有耐心等待它執行完。
怎么辦,降低數據量,先加入1000條:
還好,用時6157毫秒,6.157秒;
接着走,把數據量改為10000條:
執行完了。共117096毫秒。117.096秒,將近兩分鍾。實在是沒有耐心再測100000條的了,接下來直接測批量加入的方法。
將上面的加入到數據庫中的代碼換成以下的代碼:
dbcontext.BulkInsert(customers);
dbcontext.BulkSaveChanges();
直接上10W條:
執行完了,共3592毫秒,3.592秒,真快啊~~
那么20W呢?
20W條數據執行完,才花了6346毫秒。6.346秒的時間。比上面的方法加入1000條的數據用的時間差點兒相同,看來EF自帶的加入方法慢,是毋庸置疑的了。
為什么擴展方法用的時間這么少?
EF自帶的方法,會添加與數據庫的交互次數。一般地,EF的一個上下文在提交時會打開一個數據連接。然后把轉換成的SQL語句一條一條的發到數據庫端,然后去提交,以下的圖片是我用SQL Server Profiler記錄的和數據庫交互的操作,這僅僅是一小部分,試想。假設你的數據量達到萬級別(更不用說百萬。千萬數據了),那對數據庫的壓力是非常大的
而擴展方法執行時與數據庫的交互是這種:
批量加入的方法是生成一條SQL語句,和數據庫僅僅交互一次。那為什么圖片中有多條Insert語句呢。當你使用BulkInsert時。假設數據達到4萬之前。那在SQL的解釋時,也是非常有壓力的,有多情況下會超時,當然這與你的數據庫server有關。但為了性能與安全。將Bulk操作變為分批提交,即將上W的數據進行分解。分用1W數據量提交一次,這樣,對數據庫的壓力就小一些。