Entity Framework Bulk Insert
久違的更新
上個月到新公司後先開始熟悉新的環境,經過了莫約三個星期的教育訓練後才開始進入專案
新的專案使用到的技術也是之前沒有碰過的前端框架Angular,專案架構是前端與後端分離
.net 比較著重於API的開發上面,目前工作的內容以前端畫面顯示,客戶使用介面為主,跟之前公司的工作內容有滿大的差別
也趁這個機會好好的學習三大框架的其中之一,目前寫起來的感覺是Angular + TypeScript 比原生的JS還要舒服很多
與.net 相比起來 JS我比較沒有那麼的熟悉,使用Angular讓我少去許多必須在原生JS中要處理的作業,TypeScript在編譯期間可以即時反饋也讓我感到痛哭流涕
但無論如何TypeScript還是由JS而來,開發上對JS的熟悉度與掌握度越高,可以更佳的如魚得水
套用三井壽的名言
教練…….我真的好想學好JavaScript
真的要找段時間把JavaScript比較難理解的部分、DOM物件的操作弄清楚
另外新公司很有趣的一件事是
每隔週一都會有公司的創辦人為大家分享技術性的課程,從上課分享的內容以及深度和熱忱
願意在忙碌的工作中抽空與後輩分享相關的知識以及經驗,在程序員生涯位子往上晉升後,需要處理的事情與責任也就越多,面對專案的開發流程、架構的規劃、人力資源的調度、傾聽工程師的想法或是一場接一場的開發會議,手邊的雜事越多的情況下沒辦法將重心放在技術上面。
我真的很敬佩他即使到了這樣的高度仍然持續堅守在技術的第一線,也是學習的榜樣
最近公司開始有意規畫在未來的專案中引入單元測試,剛好上個月去上了資策會單元測試的進修課程,想趁還有些記憶整理一下上課所學到的東西
預計要寫一個簡單的單元測試例子,來熟悉一下為往後的專案開發做好準備,好了廢話到此
Entity Framework BulkInsert
最近在專案中遇到一個狀況是前端會去後端的API撈所有客戶的資料,以及相關的筆數,顯示相關的明細資料
測試人員的結論是有時候會沒辦法顯示總筆數,但我在本地端執行的時候一切正常,推論是環境造成的因素
但測試人員沒有辦法重現當時的狀況、第一時間也沒有相應的測試環境給我
面對這種沒辦法重現的Bug對開發人員來說是真的滿頭痛的,只能透過通靈的方式來處理
依據經驗推測是效能的問題後,開始往資料庫塞大量的假測資
using System.Diagnostics;
using Test.Models;
var db = new TestContext();
Console.WriteLine("測試資料寫入中");
var sw = new Stopwatch();
sw.Start();
for (int i = 1; i <= 5000000; i++)
{
var Student = new Student()
{
Number = i,
Name = $"Test {i}"
};
db.Students.Add(Student);
}
db.SaveChanges();
sw.Stop();
Console.WriteLine("測試資料寫入完畢");
Console.WriteLine($"總共花費{sw.ElapsedMilliseconds / 1000}秒");
Console.ReadLine();
一開始使用一筆一筆Add往資料庫insert
最後一次 SaveChanges
能花費更少的時間、更好的運用效能
SqlBulkCopy可以有效率地大量將資料批次寫入資料庫
若要在Entity Framework Bulk Insert 使用要先安裝套件
using System.Diagnostics;
using Test.Models;
var db = new TestContext();
Console.WriteLine("測試資料寫入中");
var sw = new Stopwatch();
sw.Start();
var StudentList = new List<Student>();
for (int i = 1; i <= 5000000; i++)
{
var Student = new Student()
{
Number = i,
Name = $"Test {i}"
};
StudentList.Add(Student);
}
db.BulkInsert(StudentList);
db.BulkSaveChanges();
sw.Stop();
Console.WriteLine("測試資料寫入完畢");
Console.WriteLine($"總共花費{sw.ElapsedMilliseconds / 1000}秒");
Console.ReadLine();
使用SqlBulkCopy批次的寫法同樣是500萬筆的資料時間只需要12秒
太神啦~~
相比之下SqlBulkCopy無論在效能或是時間上都有顯卓的提升,有了這次的經驗下次做大量的資料寫入都會優先考慮使用SqlBulkCopy的方法
有時間再來補Ado.net的寫法
4/4 補Ado.net
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
Console.WriteLine("SqlBulk批次寫入資料庫");
Stopwatch sw = new Stopwatch();
var dt = new DataTable();
dt.Columns.Add("Id", typeof(Guid));
dt.Columns.Add("Name", typeof(string));
sw.Start();
for (int i = 1; i <= 5000000; i++)
{
var dr = dt.NewRow();
dr["Id"] = Guid.NewGuid();
dr["Name"] = $"Student {i}";
dt.Rows.Add(dr);
}
string connStr = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;
using (var conn = new SqlConnection(connStr))
{
conn.Open();
using (var sqlBC = new SqlBulkCopy(connStr))
{
sqlBC.BatchSize = 100000;//設定每次批次寫入的數量
sqlBC.BulkCopyTimeout = 60;//設置逾期秒數
sqlBC.DestinationTableName = "dbo.Student";
if (dt != null && dt.Rows.Count > 0)
{
sqlBC.WriteToServer(dt);
}
}
sw.Stop();
Console.WriteLine($"總共花費{sw.ElapsedMilliseconds / 1000}秒");
}