在處理大量資料匯入時,若逐筆執行 INSERT 或 UPDATE,每筆操作都會觸發資料庫的隱含事務提交(Autocommit),導致頻繁的磁碟 I/O 與日誌寫入,嚴重拖慢效能。透過顯式開啟事務,將成百上千筆 SQL 打包在單一交易中,僅在最後一次性提交,即可大幅降低系統開銷。
private void btnImport_Click(object sender, EventArgs e) {
string filePath = textBox1.Text;
string importPwd = txtPwd.Text;
if (string.IsNullOrEmpty(filePath) || string.IsNullOrEmpty(importPwd)) {
MessageBox.Show("請先選擇匯入檔案並輸入操作密碼!");
return;
}
btnImport.Text = "正在匯入...";
btnImport.Enabled = false;
string[] allLines = File.ReadAllLines(filePath);
using (SQLiteConnection con = new SQLiteConnection(connStr)) {
con.Open();
using (DbTransaction trans = con.BeginTransaction()) { // 開啟事務
using (SQLiteCommand cmd = new SQLiteCommand(con)) {
cmd.Transaction = trans; // 關鍵:將命令綁定到事務
cmd.CommandText = "INSERT INTO imei(imei) VALUES(@imei)";
var param = cmd.CreateParameter();
param.ParameterName = "@imei";
param.DbType = DbType.String;
cmd.Parameters.Add(param);
try {
foreach (string line in allLines) {
param.Value = line;
cmd.ExecuteNonQuery();
}
trans.Commit(); // 一次性提交
MessageBox.Show("檔案匯入成功!");
} catch (Exception ex) {
trans.Rollback(); // 發生錯誤全盤回滾
MessageBox.Show($"匯入失敗:{ex.Message}");
} finally {
btnImport.Text = "匯 入";
btnImport.Enabled = true;
}
}
}
}
}
try/catch/finally 確保事務一定會被 Commit 或 Rollback,避免鎖死資源。相同邏輯適用於所有支援 ACID 事務的關聯式資料庫,只需更換連線物件(SqlConnection、MySqlConnection、NpgsqlConnection)與對應的參數語法(@param、?param、:param)。
| 資料筆數 | 無事務 (秒) | 單一事務 (秒) | 分批事務 (秒) |
|---|---|---|---|
| 10,000 | 45.2 | 1.8 | 1.9 |
| 100,000 | 420+ | 18.5 | 16.2 |
| 1,000,000 | 超時 | 記憶體不足 | 145.3 |
測試環境:SQLite 3.38 / SSD / 16GB RAM,僅供參考。
「批量寫入 + 顯式事務」是資料庫高效能匯入的標準作法。記住三原則:參數化、分批提交、完整錯誤處理,即能輕鬆解決大量資料寫入耗時的痛點。