什么是sqlldr
sqlldr是Oracle內置的工具,用來快速導入大批量數據,直接在命令行調用。
sqlldr參數
下表是sqlldr的部分參數,其中加粗的為常用參數,標紅為必需參數。
注:sqlldr的命令行參數可以直接寫在命令行,也可以放在控制文件,也可以直接放在參數文件PARFILE里面(在參數重復指定時,命令行中的參數具有最高的權重)
屬性值 含義 默認值
userid Oracle的username/password[@servicename]
control 控制文件
log 日志文件 默認與控制文件同名
bad 壞數據文件 默認與數據文件同名
discard 丟棄的數據文件
discardmax 允許丟棄數據的最大值 全部
skip 跳過的行/記錄數,比如導入的數據文件前幾行是表頭或者描述 0
load 加載的行/記錄數 全部
errors 允許的錯誤行/記錄數 50
rows 每次提交的記錄數,該參數受bindsize影響 常規路徑:64 直接路徑:全部
bindsize 每次提交記錄的緩沖區的大小(字節) 256000
silent 禁止輸出信息(header,feedback,errors,discards,partitions)
parfile 參數文件:包含參數規范的文件名
direct 使用直通路徑方式導入,不走buffer cache,通過direct path api發送數據到服務器端的加載引擎,加載引擎按照數據塊的格式處理數據並直接寫向數據文件,因此效率較高 false
parallel 並行導入,僅在直接路徑加載時有效,推薦設置true false
file 並行加載時會用到該參數,指定file參數,要加載的內容即只向指定的數據文件寫入數據,減少i/o
skip_unusable_indexes 不允許/允許不可用的索引或索引分區 false
skip_index_maintenance 不維護索引,將受影響的索引標記為不可用 false
commit_discontinued 停止加載時提交加載的行 false
readsize 緩沖區大小(字節) 1048576,最大不超過20m,該參數僅當從數據文件讀取時有效,如果是從近制文件讀取數據,則默認為64k
external_table 使用外部表進行加載 不使用
generate_only sqlldr並不執行加載,而是生成創建外部表的sql和處理數據的sql,並保存在log文件中
execute 執行外部表並加載數據
columnarrayrows 指定直接路徑加載時流緩沖區的行數 5000
streamsize 指定直接路徑加載時流緩沖區的大小(字節) 256000
multithreading 指定直接路徑加載時是否啟用多線程
date_cache 指定直接路徑加載時日期轉換用緩存大小(以條目為單位) 1000
no_index_errors 在任何索引錯誤上中止加載 false
sqlldr導入有兩種模式,常規路徑加載和直接路徑加載,默認使用常規路徑加載,當direct=y或者direct=true時,使用直接路徑加載。直接路徑加載比常規路徑擁有更高的效率,但也有諸多限制。
常規路徑加載
數據經過buffer cache,使用SQL處理數據,COMMIT提交操作,一次加載可能會涉及到多個事務處理,會產生大量undo數據(回滾數據)
通過undo回滾
觸發INSERT 觸發器
操作過程中表仍可被並發訪問
直接路徑加載
數據不經過buffer cache,從PGA直接把數據格式化成Oracle塊,再寫入數據文件,幾乎不會產生undo數據。但是如果表上有索引,會產生索引的undo數據,而且索引的塊會被讀進buffer cache,這將會花費大量時間在索引的維護上。因此,在向表中傳送大量數據時,建議先將表上的索引設置為unusable(或者使用skip_index_maintenance=true),待插入結束后,再rebuild索引 (alter index index_name rebuild nologging)
數據不會寫入HWM(高水位線)以下的數據塊,而是在HWM之后寫入,通過HWM回滾
觸發器在進行直接路徑加載之前已禁用,在加載結束時會重新啟用,如果重新啟用時不能訪問某個被引用對象,這些觸發器可能會保持為禁用狀態
操作過程中對應的表會將會被鎖定,所有在這張表上的CRUD操作將會被禁止,不能並發訪問
控制文件
控制文件為sqlldr的必需項,在這個文件里指定了數據源,編碼,操作類型,要操作的表等一系列參數,控制文件常見設置如下:
--關閉歸檔日志,提高導入速度(僅直接路徑時有效)
--unrecoverable
load data
--指定編碼
characterset 'UTF8'
--1.指定要加載的數據文件
--INFILE 和INDDN是同義詞,它們后面都是要加載的數據文件。如果用 * 則表示數據就在控制文件內。
[ { INFILE | INDDN } {file | * } ]
--BADFILE和BADDN是同義詞。file指定壞數據保存的文件
[{ BADFILE | BADDN } file ]
--DISCARDFILE和DISCARDDN是同義詞。file指定丟棄的數據文件
[{ DISCARDFILE | DISCARDDN } file ]
--2.指定操作類型
--insert:默認值,裝載空表,如果原先的表有數據,sqlloader會停止
--append:原先的表有數據 就在表中追加新記錄
--replace:刪除舊記錄(用 delete from table 語句),替換成新裝載的記錄
--truncate:刪除舊記錄(用 truncate table 語句),替換成新裝載的記錄
[ APPEND | REPLACE | INSERT | TRUNCATE ]
--3.指定操作的表
INTO TABLE [user.]table
--4.指定過濾條件
--[when id = id_memo]
--5.指定字段分隔符
--字段分隔符
fields terminated by ','
--字段用什么字符包括起來
optionally enclosed by '"'
--字段沒有對應的值時允許為空
trailing nullcols
--6.指定表字段
--常見數據類型
--CHAR 字符
--DATE 日期
--INTEGER 整數
--FLOAT 普通符點
--DOUBLE 雙精度符點
(
id,--類型未指定時,默認為character,每個字段的實際解析類型見log文件
code integer,
name char(1000),
sum double,
create_date date "yyyy-mm-dd hh24:mi:ss",
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
執行sqlldr
編寫好控制文件test.ctl后,就可以通過命令行執行導入,由於我使用的數據源文件為PL/SQL直接導出的csv文件,因此要跳過第一行記錄(表頭),以下為windows下的使用示例:
//常規路徑
//調整每次提交的行數和緩沖區大小,以減少事務提交的次數
sqlldr userid=xxx/xxxxxx@xxxxxx control=test.ctl log=test.log skip=1 rows=5000 bindsize=20971520 readsize=20971520
//直接路徑
//開啟parallel和unrecoverable(控制文件中)
sqlldr userid=xxx/xxxxxx@xxxxxx control=test.ctl log=test.log skip=1 direct=true parallel=true skip_index_maintenance=true readsize=20971520 columnarrayrows=10000 streamsize=20971520 date_cache=5000
1
2
3
4
5
6
7
執行完后,結果將會保存至test.log文件中(不管成功還是失敗),經測試,200萬數據,使用常規路徑加載在有索引的情況下導入時間約為15分鍾左右,使用直接路徑加載導入時間約為4分鍾左右。
常見問題及解決
1.數據文件的字段超出最大長度:
檢查報錯字段長度是否超過255,若超過255,需要在控制文件中指明字段長度,如:char(1000),否則Oracle會默認該字段為VARCHAR(255)/CHAR(255)
2. TERMINATED 和 ENCLOSED 字段后沒有終止定界符:
1).檢查數據源文件是否格式正確
2).檢查報錯字段的前一個字段是否為數字,如果該字段為數字,並且在控制文件中指定了數據類型,嘗試將指定的數據類型刪掉,使用默認的類型,避免轉換時匹配不一致
3. ORA-01722: 無效數字:
檢查報錯字段在控制文件中是否指定了數據類型,嘗試將指定的數據類型刪掉,使用默認的類型,避免轉換時匹配不一致
4.ORA-01438: 值大於為此列指定的允許精度:
檢查數據庫字段類型與控制文件中指定的字段類型是否一致
5.SQL*Loader-700: 執行重要的分配 [7] 時內存耗盡:
這個異常一般發生在直接路徑加載時,如果表字段很多,或者每次向內存加載的行數過大時(columnarrayrows),sql*loader無法向系統申請到足夠的內存空間,就會報出out of memory的錯誤。
檢查執行的命令行里是否包含columnarrayrows參數,如果有,將該參數的值調小,如果沒有,加入該參數並且設置值小於5000(5000為默認值)
6.sqlldr不是內部命令或外部命令:
sqlldr.exe在Oracle安裝路徑的BIN文件夾里,先檢查是否安裝Oracle,如果未安裝,則需要安裝Oracle;如果已安裝,則檢查環境變量PATH是否包含Oracle安裝路徑的BIN文件夾,如果沒有,在Path后加上Oracle_Path\BIN
7.SQL*Loader-704: 內部錯誤: ulconnect: OCIServerAttach [0]
ORA-12154: TNS: 無法解析指定的連接標識符
檢查命令行userid參數的值username/password[@servicename]是否正確
8.sqlldr導入中文亂碼:
檢查Oracle導出服務端與導入服務端字符集是否一致
select * from v$nls_parameters t where t.PARAMETER = 'NLS_CHARACTERSET';
1
若不一致,則將控制文件里的characterset參數改為與導出服務端字符集一致即可
characterset ‘ZHS16GBK’
————————————————
版權聲明:本文為CSDN博主「RELAXXXXXXX」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/labixiaofeng/article/details/85698899