SQL*Loader 是 Oracle 官方提供的高性能數據加載工具,廣泛應用於數據倉庫初始裝載、ETL 增量同步、異構遷移等場景。其核心優勢在於 直接路徑加載:繞過 SQL 引擎、緩存、Undo 生成,直寫數據塊至高水位線 (HWM) 以上。本文深度剖析架構組件、控制文件語法、直接路徑原理與限制、並行加載策略及常見錯誤處理。

| 組件 | 角色 | 關鍵參數/文件 |
|---|---|---|
| 控制文件 | 核心指揮官:定義數據格式、映射規則、加載策略 | CONTROL=xxx.ctl |
| 數據文件 | 源數據載體:CSV、定長、變長、流格式等 | DATA=xxx.dat 或控制文件內 INFILE |
| 參數文件 | 運行時參數集中管理 (可選) | PARFILE=xxx.par |
| 日志文件 | 完整執行過程記錄:統計、錯誤、性能指標 | LOG=xxx.log |
| 錯誤文件 | 格式/類型不匹配記錄 (BAD) | BAD=xxx.bad |
| 丟棄文件 | 邏輯條件過濾記錄 (DISCARD) | DISCARD=xxx.dsc, DISCARDMAX |

| 維度 | 常規路徑 | 直接路徑 |
|---|---|---|
| 數據流向 | SQL 引擎 → 緩存 → 數據塊 | 直寫數據塊 (HWM 以上) |
| Undo 生成 | 完整 Undo (數據 + 字典) | 極少 Undo (僅字典) |
| Redo 生成 | 標準 Redo | 可 NOLOGGING 極少 Redo |
| 高水位線 (HWM) | 逐塊推進 | 直接跳過空間,HWM 大幅前移 |
| 索引維護 | 同步維護 | 延遲維護 (SKIP_INDEX_MAINTENANCE) 或並行重建 |
| 觸發器/約束 | 全觸發 | 不觸發行級觸發器,約束延遲驗證 |
| 並行度 | 單線程 | 支援並行 (PARALLEL=TRUE) |
| 適用場景 | 小數據量、需觸發器、OLTP 混載 | 大批量初始裝載、數倉 ETL、遷移 |
LOAD DATA
INFILE 'data.csv' -- 數據文件
BADFILE 'data.bad' -- 錯誤文件
DISCARDFILE 'data.dsc' -- 丟棄文件
APPEND -- 加載模式: INSERT/APPEND/REPLACE/TRUNCATE
INTO TABLE target_table -- 目標表
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' -- 分隔符
TRAILING NULLCOLS -- 允許尾部空值
(
col1 CHAR(10), -- 固定長度字符
col2 INTEGER EXTERNAL, -- 外部數值格式
col3 DATE 'YYYY-MM-DD', -- 日期格式
col4 DECIMAL EXTERNAL (10,2),
col5 FILLER, -- 忽略該列
col6 EXPRESSION "UPPER(:col1)", -- SQL 表達式
col7 CONSTANT 'DEFAULT_VAL' -- 常量值
)
INSERT:表必須為空,否則報錯APPEND:追加數據 (最常用)REPLACE:DELETE FROM table 後加載TRUNCATE:TRUNCATE TABLE 後加載 (高效,不可回滾)-- 命令行或參數文件
DIRECT=TRUE
PARALLEL=TRUE -- 並行加載 (需配合多會話、分區表)
SKIP_INDEX_MAINTENANCE=TRUE -- 跳過索引維護,加載後手動 REBUILD
ERRORS=100000 -- 最大錯誤容忍數
ROWS=10000 -- 綁定陣列大小 (常規路徑)
READSIZE=20971520 -- 讀取緩衝區 (20MB)
BINDSIZE=20971520 -- 綁定緩衝區
ALTER TABLE ... MOVE 或 TRUNCATE)INSERT INTO ... SELECT、MERGE、OCI 直接路徑 API-- 前提:表為分區表 或 使用多個數據文件 + 多個控制文件
-- 會話 1
sqlldr userid=scott/tiger control=load_p1.ctl DIRECT=TRUE PARALLEL=TRUE DATA=data_p1.dat
-- 會話 2
sqlldr userid=scott/tiger control=load_p2.ctl DIRECT=TRUE PARALLEL=TRUE DATA=data_p2.dat
-- 控制文件關鍵差異
-- load_p1.ctl: INTO TABLE sales PARTITION (p1) ...
-- load_p2.ctl: INTO TABLE sales PARTITION (p2) ...
並行加載後必須手動重建索引:ALTER INDEX idx_name REBUILD PARALLEL 8;
READSIZE=50M BINDSIZE=50M 減少系統調用DROP INDEX / UNUSABLE,加載後並行 REBUILDALTER TABLE ... DISABLE CONSTRAINT ...,事後 ENABLE NOVALIDATE 快速驗證ALTER TABLE ... NOLOGGING + 直接路徑 = 極少 RedoERRORS 參數控制容錯| 錯誤現象 | 根因 | 解決 |
|---|---|---|
| ORA-01652: unable to extend temp segment | 直接路徑排序溢寫 Temp 表空間不足 | 擴充 Temp、增加 SORT_AREA_SIZE、分片並行 |
| ORA-00054: resource busy | 表被鎖定 (DDL、長事務、其他加載) | 等待釋放、殺掉阻塞會話、離峰時段運行 |
| 數據截斷/轉換錯誤進 BAD 文件 | 控制文件定義與數據不符 | 檢查 CHAR(n) 長度、日期格式、數值精度 |
| 直接路徑加載後索引 UNUSABLE | SKIP_INDEX_MAINTENANCE=TRUE 或並行加載 |
ALTER INDEX ... REBUILD |
| ORA-26015: index cannot be maintained | 唯一索引衝突 (直接路徑不檢查唯一性) | 加載前 DISABLE VALIDATE CONSTRAINT 或去重 |
-- 創建外部表映射 CSV 文件
CREATE TABLE ext_sales (
prod_id NUMBER, cust_id NUMBER, amount NUMBER, sale_date DATE
)
ORGANIZATION EXTERNAL (
TYPE ORACLE_LOADER
DEFAULT DIRECTORY data_dir
ACCESS PARAMETERS (
RECORDS DELIMITED BY NEWLINE
FIELDS TERMINATED BY ','
MISSING FIELD VALUES ARE NULL
)
LOCATION ('sales_*.csv')
)
PARALLEL 4
REJECT LIMIT UNLIMITED;
-- 直接路徑插入 (並行、無日志)
INSERT /*+ APPEND PARALLEL(8) */ INTO sales
SELECT * FROM ext_sales;
外部表優勢:可用 SQL 查詢/過濾/轉換、支援並行、無需控制文件、易於管道化 ETL。
SQL*Loader 直接路徑加載是 Oracle 大批量數據入庫的「核武器」:繞過 SQL 層、最小化 Undo/Redo、並行直寫 HWM 以上。掌握 控制文件語法、DIRECT/PARALLEL 參數、索引/約束策略、錯誤處理機制,配合外部表現代化替代方案,即可構建企業級高性能數據加載體系。