伺服器運行產生大量 Log 檔案(40 萬筆+),需分析資料。嘗試以 C++ 讀取檔案逐筆 INSERT 入庫,耗時 1 小時以上,完全無法接受。
bcp.exe),支援文字檔、原生格式高速匯入/匯出。xp_cmdshell 在 T-SQL 中呼叫,或直接在作業系統層執行。
EXEC master..xp_cmdshell
'bcp DatabaseName..TableName in "FilePath" -c -t"Delimiter" -S"ServerName" -U"UserName" -P"Password"';
| 參數 | 說明 |
|---|---|
| in | 匯入模式(out 為匯出) |
| -c | 字元模式(預設 tab 分隔、換行結束) |
| -t"Delimiter" | 指定欄位分隔符(如 -t"," 為 CSV) |
| -S | 目標伺服器名稱 |
| -U / -P | 登入帳號密碼 |
| -f format_file | 使用格式化檔案(複雜對應時) |
| -b batch_size | 批次大小(預設全部),建議 10000-50000 |
| -h "TABLOCK" | 大量載入提示,鎖定整張表加速 |
// 1. 產生 .bat 內容(不含 xp_cmdshell,直接是 bcp 命令)
AnsiString batContent =
"bcp MyDB..MyTable in \"C:\\Data\\log.txt\" "
"-c -t\",\" -S\"MyServer\" -U\"sa\" -P\"pwd\" -b 50000 -h \"TABLOCK\"";
// 2. 寫入暫存 .bat 檔
AnsiString batPath = "C:\\Temp\\import_log.bat";
std::ofstream ofs(batPath.c_str());
ofs << batContent.c_str();
ofs.close();
// 3. 執行 .bat(非同步或同步視需求)
HINSTANCE hResult = ShellExecute(
NULL, "open", batPath.c_str(), NULL, NULL, SW_HIDE
);
if ((int)hResult <= 32) {
// 執行失敗處理
}
| 方式 | 40 萬筆耗時 | 備註 |
|---|---|---|
| 逐筆 INSERT (C++ 讀檔 + SQL) | ~ 1 小時+ | 網路往返、解析編譯、記錄日誌逐筆 |
| BCP 批次匯入 | ~ 7 分鐘 | 大量載入路徑、最小化記錄、鎖定優化 |
| BULK INSERT (T-SQL) | ~ 5-6 分鐘 | 在資料庫引擎內執行,無進程切換開銷 |
BULK INSERT TableName FROM 'FilePath' WITH (FIELDTERMINATOR=',', ROWTERMINATOR='\n', BATCHSIZE=50000, TABLOCK); — 純資料庫端執行,效能略優於 BCP。WriteToServer(DataTable) 或 WriteToServer(IDataReader),物件導向、型別安全、支援 ColumnMappings。-f fmt.fmt。bulkadmin 伺服器角色或 INSERT 權限 + ADMINISTER BULK OPERATIONS。-e err.log 導出錯誤列,匯入後檢查錯誤日誌。-c 使用 ANSI/MBCS;Unicode 檔案用 -w (寬字元)。-h "CHECK_CONSTRAINTS" 或 FIRE_TRIGGERS。大量文字檔匯入 SQL Server,**BCP/BULK INSERT/SqlBulkCopy** 是標準高效路徑,效能較逐筆 INSERT 提升 10-100 倍。C++ 應用可透過 ShellExecute 呼叫 .bat 包裝 BCP,或改用 ADO/OLE DB 直接呼叫 BULK INSERT,避免外部進程依賴。