測試場景
- 目標表
CALLS (PK: CALL_ID, IDX: CALL_DATE),導入 10 萬筆、約 6MB CSV 檔。
- 環境:Oracle 9i/10g,測量總耗時與 CPU 佔用。
四種方法效能對比
| 方法 | 關鍵技巧 | 總耗時 (秒) | CPU 時間 (秒) | 適用場景 |
| 1. 單行 INSERT | 逐行解析、執行、索引維護 | 172 | 52 | 極少量種子資料、腳本部署 |
| 2. 無索引單行 INSERT | 先 DROP 索引/PK,導入後重建 | 130 | 35 | 空表大量導入、索引重建成本可接受 |
| 3. OCI 批次陣列綁定 | 陣列 100 行/次,單次解析、批次執行,配合無索引 | 14 | 7 | 高效能導入、需 OCI 支援 (Pro*C, ODP.NET, JDBC batch) |
| 4. SQL*Loader 直接路徑 | 繞過 SQL 層、直接格式化資料區塊寫入、NOLOGGING | ~5 (估算) | ~2 | 超大量 (百萬級以上)、初始載入、資料倉儲 ETL |
方法 3 批次陣列綁定實作要點 (以 ODP.NET 為例)
using (var conn = new OracleConnection(cs))
using (var cmd = new OracleCommand("INSERT INTO CALLS VALUES (:1,:2,:3,:4,:5)", conn)) {
cmd.ArrayBindCount = 10000; -- 批次筆數
cmd.Parameters.Add(":1", OracleDbType.Int32, callIds, ParameterDirection.Input);
cmd.Parameters.Add(":2", OracleDbType.Date, callDates, ParameterDirection.Input);
cmd.Parameters.Add(":3", OracleDbType.Int32, empIds, ParameterDirection.Input);
cmd.Parameters.Add(":4", OracleDbType.Varchar2, callTypes, ParameterDirection.Input);
cmd.Parameters.Add(":5", OracleDbType.Varchar2, details, ParameterDirection.Input);
conn.Open();
cmd.ExecuteNonQuery(); -- 單次網路往返完成 10000 筆
}
關鍵優化參數
SORT_AREA_SIZE (Session 級) 加大 → 索引建立排序更多在記憶體完成。
NOLOGGING 建立索引/載入 → 減少 Redo 產生,注意:會影響 Data Guard 同步與時間點恢復,需權衡。
UNRECOVERABLE (舊版關鍵字) 同 NOLOGGING。
避坑指南
- 表已有海量資料時,不可 刪除索引導入 (重建索引成本 > 導入節省)。
- 批次大小視 PGA 記憶體而定,過大導致 Swap 反而變慢。
- 直接路徑載入 (SQL*Loader, 外部表, CTAS) 需表無觸發器、外鍵、啟用約束。