EntityFramework Core 5.0 VS SQLBulkCopy
EntityFramework Core 5.0 VS SQLBulkCopy
EF Core 5.0伴隨著.NET 5.0釋出已有一段時日,本節我們來預估當大批量新增資料時,大概是多少區間我們應該考慮SQLBulkCopy而不是EF Core
SQLBulkCopy早出現於.NET Framework 2.0,將資料批量寫入利用此類毫無疑問最佳,雖其來源任意,但此類僅適用於SQL Server,每個關聯式資料庫都有其批量處理驅動,這裡我們僅僅只討論SQL Server
效能差異預估批量資料大小
首先給出我們需要用到的測試模型
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EFCOREDB
{
public class Test
{
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public DateTime CreateDateTime { get; set; }
}
}
接下來我們則需要模擬資料,為偽造實際生產資料,這裡我們介紹一個包Bogus,此包專用來偽造資料,一直在更新從未間斷,版本也達到32,如下:
此包中有針對使用者類的模擬,具體使用這裡就不詳細展開,我們構造一個方法來偽造指定數量的使用者資料,如下:
using Bogus;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EFCOREDB
{
/// <summary>
/// 產生模擬資料
/// </summary>
public class GenerateMockData
{
/// <summary>
/// 產生指定資料量的資料
/// </summary>
/// <param name="count"></param>
/// <returns></returns>
public static IEnumerable<Test> GetTests(int count)
{
var profileGenerator = new Faker<Test>()
.RuleFor(p => p.Title, v => v.Person.FirstName)
.RuleFor(p => p.Content, v => v.Person.LastName)
.RuleFor(p => p.CreateDateTime, v => v.Person.DateOfBirth);
return profileGenerator.Generate(count);
}
}
}
有了批量偽造資料,接下來我們再利用上下文去新增資料,然後分別列印偽造資料和新增成功所耗費時間,如下:
/// <summary>
/// EntityFramework Core 5.0 上下文去新增資料,然後分別列印偽造資料和新增成功所耗費時間
/// </summary>
public static async void TestGenerateInsertAndInsertWithEFCoreData()
{
Console.WriteLine("產生模擬資料");
var stopwatch = new Stopwatch();
stopwatch.Start();
var data = GenerateMockData.GetTests(10000);
//產生10條模擬資料
//產生模擬資料, 花費時間:0.2591446 秒
//產生模擬資料, 花費時間:0.2591446 秒,插入資料的資料數量: 10,插入資料花費時間: 0.2411458
//產生10000條模擬資料
//產生模擬資料,花費時間:0.9874856 秒
//產生模擬資料,花費時間:0.9874856 秒,插入資料的資料數量: 10000,插入資料花費時間: 1.4542355
var TotalSeconds = stopwatch.Elapsed.TotalSeconds;
Console.WriteLine($"產生模擬資料,花費時間:{TotalSeconds} 秒");
//上下文去新增資料,然後分別列印偽造資料和新增成功所耗費時間
var datetime1 = DateTime.Now;
using var EFCoreVSSqlBulkCopyContext = new EFCoreVSSqlBulkCopyContext() { CreateDateTime = datetime1 };
EFCoreVSSqlBulkCopyContext.Database.EnsureCreated();
stopwatch.Restart();
EFCoreVSSqlBulkCopyContext.Tests.AddRange(data);
await EFCoreVSSqlBulkCopyContext.AddRangeAsync(data);
var result = await EFCoreVSSqlBulkCopyContext.SaveChangesAsync();
Console.WriteLine($"產生模擬資料,花費時間:{TotalSeconds} 秒,插入資料的資料數量:{result},插入資料花費時間:{stopwatch.Elapsed.TotalSeconds}");
}
新增100條資料太小,這裡我們直接從批量10000條資料開始測試,此時我們將看到所儲存資料和實際資料完全一樣
通過SQL Server Profiler工具監控得到如下一堆語句如下
通過執行多次,當然也和筆記本配置有關(i7,6核,記憶體8G),但還是可以預估批量新增1000條大概耗時為毫秒級,如下:
當然你也可所以使用十萬條或者百萬條資料,由於本電腦的配置,因此沒有測試使用十萬條或者百萬條資料,有興趣的可以再往上增長資料自己測試一下,
接下來我們來看看利用SqlBulkCopy看看效能如何
/// <summary>
/// SQLBulkCopy 上下文去新增資料,然後分別列印偽造資料和新增成功所耗費時間
/// </summary>
public static async void TestGenerateAndInsertWithSqlBulkCopyData()
{
Console.WriteLine("產生模擬資料");
var stopwatch = new Stopwatch();
stopwatch.Start();
var data = GenerateMockData.GetTests(10000);
//產生10000條模擬資料
//產生模擬資料,花費時間:1.0126009 秒
//產生模擬資料, 花費時間:1.0126009 秒,插入資料的資料數量: 10000,插入資料花費時間: 0.3210853
var TotalSeconds = stopwatch.Elapsed.TotalSeconds;
Console.WriteLine($"產生模擬資料,花費時間:{TotalSeconds} 秒");
//上下文去新增資料,然後分別列印偽造資料和新增成功所耗費時間
var datetime1 = DateTime.Now;
using (var EFCoreVSSqlBulkCopyContext = new EFCoreVSSqlBulkCopyContext() { CreateDateTime = datetime1 })
{
EFCoreVSSqlBulkCopyContext.Database.EnsureCreated();
}
stopwatch.Restart();
var dt = new DataTable();
dt.Columns.Add("Id");
dt.Columns.Add("Title");
dt.Columns.Add("Content");
dt.Columns.Add("CreateDateTime");
foreach (var item in data)
{
dt.Rows.Add(item.Id, item.Title, item.Content, item.CreateDateTime);
}
//注意DestinationTableName 必須是全路徑即 資料庫名稱.架構名稱.表名稱
using var sqlbulkcopy = new SqlBulkCopy("server=127.0.0.1;database=EFCoreVSSqlBulkCopyContext;user=sa;password=sa123;") { DestinationTableName = "EFCoreVSSqlBulkCopyContext.dbo.[20201208]" };
await sqlbulkcopy.WriteToServerAsync(dt);
Console.WriteLine($"產生模擬資料,花費時間:{TotalSeconds} 秒,插入資料的資料數量:{10000},插入資料花費時間:{stopwatch.Elapsed.TotalSeconds}");
}
因如上利用EF Core新增時間在毫秒級,那麼我們則直接從新增1萬條開始測試,如下我們可看到此時與EF Core新增1萬條資料差異,耗時遠遠小於1.6秒
還可以繼續增長資料,本文不在展示測試結果,測試10萬條資料很顯然EF Core耗時結果將為SqlBulkCopy的指數倍(大致14倍,若資料為100萬,想想二者其效能差異)
若繼續通過SQL Server Profiler監控工具檢視SQL語句,很顯然SQL語句會很簡短,據我所知,SqlBulkCopy是直接將資料通過流形式傳輸到資料庫伺服器,然後一次性插入到目標表中,所以效能是槓槓的。
利用SqlBulkCopy和EF Core 5.0,當然理論上不論是EF Core更新到其他任何版本,其效能與SqlBulkCopy不可同日而語,本文我們只是稍加探討下資料量達到多少時不得不考慮其他手段來處理,而不是利用EF Core新增資料
EF Core和SqlBulkCopy效能差異比較,毫無疑問SqlBulkCopy為最佳選手,當新增資料量達到1萬+時,若需考慮效能,可採用SqlBulkCopy或其他手段處理資料而不再是EF Core,二者效能差異將呈指數增長
相關文章
- EntityFramework Core健康檢查Framework
- [翻譯]EntityFramework Core 2.2 釋出Framework
- EntityFramework Core筆記:入門(1)Framework筆記
- EntityFramework Core併發遷移解決方案Framework
- EntityFramework Core如何對映動態模型?Framework模型
- EntityFramework Core筆記:儲存資料(4)Framework筆記
- EntityFramework Core筆記:查詢資料(3)Framework筆記
- EntityFramework Core 遷移忽略主外來鍵關係Framework
- EntityFramework Core上下文例項池原理分析Framework
- ASP.Net Core5.0 EF Core使用記錄ASP.NET
- 【譯】Announcing Entity Framework Core 5.0 Preview 5FrameworkView
- EntityFramework Core筆記:表結構及資料基本操作(2)Framework筆記
- ASP.NET Core Identity自定義資料庫結構和完全使用Dapper而非EntityFramework CoreASP.NETIDE資料庫APPFramework
- Entityframework MigrationsFramework
- C#ASP.Net Core 5.0 使用StackExchange.RedisC#ASP.NETRedis
- .NET Core/.NET 5.0 解構函式依然有效?函式
- Workflow Core + asp.net core 5.0 實現簡單審批工作流ASP.NET
- RocketMQ 5.0 vs 4.9.X 圖解架構對比MQ圖解架構
- 基於.Net Core 5.0 Worker Service 的 Quart 服務
- ASP.NET Core Web Api之JWT VS Session VS Cookie(二)ASP.NETWebAPIJWTSessionCookie
- 在EntityFramework6中管理DbContext的正確方式(3)【環境上下文DbContext vs 顯式DbContext vs 注入DbContext】FrameworkContext
- 硬剛谷歌 GMS,華為 HMS Core 5.0 憑什麼?谷歌
- Blog.Core 專案已完成升級.NET5.0
- EntityFramework Core不得不注意的效能優化意外收穫,你會用錯?Framework優化
- ASP.NET Core 5.0 MVC中的 Razor 頁面 介紹ASP.NETMVC
- EntityFramework 優化建議Framework優化
- EntityFramework使用及優化Framework優化
- 虛擬機器 之 Fedora Core 5.0 用 Xen 虛擬Slackware 10.2虛擬機
- 自動註冊實體類到EntityFramework Core上下文,並適配ABP及ABP VNextFramework
- VS2022-建立 ASP.NET Core Web 應用ASP.NETWeb
- 如何使用 VS Code 開發.NET Core應用程式
- 資料訪問 - EntityFramework整合Framework
- EntityFramework優化:查詢WITH(NOLOCK)Framework優化
- EntityFramework優化:查詢效能Framework優化
- HMS Core 5.0:全球第三大移動應用生態破土而出
- GitHub自動化部署(CD) asp.net core 5.0 專案(免費空間)GithubASP.NET
- C#|.net core 基礎 - 值傳遞 vs 引用傳遞C#
- ASP.Net 管道模型 VS Asp.Net Core 管道 總結ASP.NET模型