MSSQL 和 MariaDB 寫入大量資料
MSSQL 批次寫入
Bulk Insert 是 MSSQL 提供給大量寫入資料庫的一個好用的語法,適用於一次性寫入數十萬甚至數千萬筆的資料,其主要由底下兩個實體檔案所組成。
- Format File(格式檔):用來定義要寫入的數據結構。
- 資料文字檔:實際要導入的數據,例如 CSV 或 TXT 檔案。
Format File
SQL Server 支援兩種類型的格式檔案:非 XML 格式和 XML 格式。 非 XML 格式是舊版 SQL Server 所支援的原始格式,詳細的說明可參考官網,這邊我就用非 XML 格式,也就是文字檔的格式來說明。
圖片來源 : 使用非 XML 格式檔案 (SQL Server) |
- 第一行 9.0 表示 bcp 公用程式的版本號碼版本(9.0 代表 SQL Server 2005),如果你使用的是 2008、2012、2019 等更新的版本,他是可以下向相容的。
- 還有最後一行要記得根據資料檔案內實際的換行符號來定義,Windows 通常是 \r\n。
MSSQL 範例檔案
建立資料表
CREATE TABLE MyTable ( PersonID varchar(10), UserName nvarchar(10), Memo nvarchar(15) );
Format File
本範例儲存在 C:\BulkInserPOC\MsSql.fmt
9.0 3 1 SQLCHAR 0 5 "" 1 PersonID "" 2 SQLCHAR 0 10 "" 2 Name "" 3 SQLCHAR 0 15 "\r\n" 3 Memo ""
資料文字檔案
本範例儲存在 C:\BulkInserPOC\MsSqlData.txt,還有舊版在 Windows 環境下僅支援 ANSI,請務必小心編碼,不要改成 UTF-8,編碼錯誤會踩到雷的【SQL Server 2016 (13.x) 之前的版本不支援字碼頁 65001 (UTF-8 編碼)】。
1345612345678 abcedfgh La 2345 1234567890張 小 藍 3345 123456789 Lawrence 沈
執行語法
在 SQL Server 的環境下實際測試,執行 100,737 筆,僅需 0.476 秒。
BULK INSERT MyTable FROM 'C:\BulkInserPOC\MsSqlData.txt' WITH ( FORMATFILE = 'C:\BulkInserPOC\MsSql.fmt' -- , CODEPAGE = '950' -- 非必要 );
MariaDB 也支援大量寫入的語法 LOAD DATA INFILE ,但比較可惜的是它沒有類似 Format File 的檔案可以定義資料結構,而是使用指定的分隔符號(預設是 Tab)來切割各欄位,因此若資料內容有包含到指定的分隔符號,可能會導致切割錯誤,這點在使用上需要注意一下。
MariaDB 範例檔案
建立資料表
CREATE TABLE MyTable ( PersonID VARCHAR(10), UserName VARCHAR(10), Memo VARCHAR(15) ) CHARACTER SET utf8mb4;
資料文字檔案
本範例儲存在 C:\BulkInserPOC\MySqlData.txt,我的案例因為某種因素無法改變檔案編碼,該文字檔編碼為 big-5,所以在執行批次寫入的時候記得指定編碼。
13456~~12345678 ~~abcedfgh La 22345~~1233545~~張 小 藍 3345~~123456789~~Lawrence 沈
執行語法
在 MariaDB 的環境下實際測試,執行 100,737 筆,僅需 0.9 秒。
LOAD DATA LOCAL INFILE 'C:/BulkInserPOC/MySqlData.txt' INTO TABLE MyTable CHARACTER SET big5 -- 根據需求調整 FIELDS TERMINATED BY '~~' -- 使用 ~~ 來分隔欄位 LINES TERMINATED BY '\r\n'
可能遇到的問題
在 MariaDB 中 LOAD DATA LOCAL INFILE 預設是被停用,因此執行上述語法可能會收到某些錯誤,若是此問題的話,必須在連線字串中設定 AllowLoadLocalInfile=true。
另外如果你剛好跟我一樣使用 MySqlConnector 這個套件來連接 MariaDB 的話,或許也可以直接使用該套件提供的 MySqlBulkLoader 類別 來達成批次寫入目的,雖然我沒有特別去查看該套件的原始碼,但我猜背後的原理應該也是協助我們完成上述的 SQL 語法吧!!
// MySqlConnector 套件官方 Sample Code using var connection = new MySqlConnection("...;AllowLoadLocalInfile=True"); await connection.OpenAsync(); var bulkLoader = new MySqlBulkLoader(connection) { FileName = @"C:\Path\To\file.csv", TableName = "destination", CharacterSet = "UTF8", NumberOfLinesToSkip = 1, FieldTerminator = ",", FieldQuotationCharacter = '"', FieldQuotationOptional = true, Local = true, } var rowCount = await bulkLoader.LoadAsync();
留言
張貼留言
您好,我是 Lawrence,這裡是我的開發筆記的網誌,如果你對我的文章有任何疑問或者有錯誤的話,歡迎留言讓我知道。