針對 SQL Server 大批量插入,本文對比五大技術方案:循環調用存儲過程、SqlBulkCopy、表值參數(TVP)、字符串拼接拆分、異步隊列。通過 1K/10K/100W 三檔測試數據,給出明確選型建議。
| 方案 | 原理 | 適用規模 | 優點 | 缺點 |
|---|---|---|---|---|
| 1. 循環調用 SP | 逐行 EXEC sp_insert | < 1K | 簡單、兼容舊版本 | 網絡往返多、上下文切換重、極慢 |
| 2. SqlBulkCopy | ADO.NET 批量複製流 | 1K - 1000W+ | 極快、流式內存、支援 BatchSize/NotifyAfter | 需 .NET 環境、列映射嚴格 |
| 3. 表值參數 (TVP) | 用戶定義表類型傳參 | < 1K 最優,>1K 性能下降 | 集合操作、單次往返、類型安全 | SQL Server 2008+、內存壓力大、>1000 行需分批 |
| 4. 字符串拼接拆分 | CSV 傳入 SP 再 SPLIT | < 10K | 無需新建類型 | 拆分邏輯複雜、長度限制、注入風險 |
| 5. 異步隊列 | 生產者-消費者模式 | 極大/削峰填谷 | 解耦、可重試、平滑寫入 | 架構複雜、最終一致性、延遲 |
CREATE TYPE PassportTableType AS TABLE (PassportKey NVARCHAR(50));CREATE PROCEDURE CreatePassportWithTVP @TVP PassportTableType READONLY AS INSERT INTO Passport(PassportKey) SELECT PassportKey FROM @TVP;DataTable dt = ...; SqlParameter p = new SqlParameter("@TVP", dt) { TypeName = "PassportTableType" }; cmd.Parameters.Add(p); cmd.ExecuteNonQuery();| 數據量 | 循環 SP (ms) | SqlBulkCopy (ms) | TVP (ms) |
|---|---|---|---|
| 1,000 | ~2,500 | ~15 | ~20 |
| 10,000 | ~25,000 | ~120 | ~180 |
| 1,000,000 | ~2,500,000 | ~8,000 | ~25,000 (內存壓力大) |
var bulk = new SqlBulkCopy(connStr, SqlBulkCopyOptions.TableLock | SqlBulkCopyOptions.CheckConstraints);
bulk.DestinationTableName = "Passport";
bulk.BatchSize = 5000; // 批次提交,平衡事務日誌與鎖
bulk.BulkCopyTimeout = 600; // 10 分鐘超時
bulk.EnableStreaming = true; // 大數據流式讀取,不全載入內存
bulk.ColumnMappings.Add("PassportKey", "PassportKey"); // 顯式映射
bulk.WriteToServer(dataTable);
SqlBulkCopyOptions.FireTriggersSqlBulkCopyOptions.KeepIdentityNOCHECK CONSTRAINT 導入後 CHECK CONSTRAINTCharacter Set=utf8(MySQL)或確保 SQL Server 排序規則一致百萬級首選 SqlBulkCopy,千級高頻用 TVP,
循環 SP 進博物館,異步隊列做削峰。
BatchSize 調優記心間,ColumnMappings 顯式全。
備份驗證少不了,上線前必壓測。