Sql*Loader經常使用知識

平常中,大量有格式的數據存放在平面文件中,如csv、txt中。經過sql*loader能夠很方便導入到oracle數據庫中。web

 
先看一個例子,把平面文件test_action.txt中的數據導入到test_action表中。
test_action.txt
--------
"2012-06-25 00:03:01","5D8969C289594C4FE76188066C4D72C4","official","newwap","boutique_product","0","140","x39x0xxx89x3x","S60V52","45"
--------
 
test_action表結構
 
控制文件
test_action.ctl
----
load data
CHARACTERSET UTF8
infile '/home/oracle/test_action.txt'
append into table scott.test_p2sp
fields terminated by ","      - -我的理解:以逗號分隔各列(根據文本文件數據的樣式變化),若上文中的文本用空格,此處應更爲‘ ’
                                                                     "2012-06-25 00:03:01" "5D8969C289594C4FE76188066C4D72C4" "official" "newwap" "boutique_product" "0" "140" "x39x0xxx89x3x" "S60V52" "45"
optionally enclosed by '"'  - -我的理解:一樣根據文本文件而定,例本文中的(如上數據),均採用" "各用來標識一列。
                                                                      若採用冒號,空格,逗號等其餘亦可( xxx )(,xxx,)  (:xxx:)
                                                                                                                                                
(LOG_TIME date "yyyy-mm-dd hh24:mi:ss",MD5ID,CHANNEL,SUB_CHANNEL,ACTION_TYPE,STATUS,VER,IMEI,MBL,PRODUCT_ID )
----
 
導入語句
$ sqllder user/password errors=1000 control='/home/oracle/test_action.ctl' 
 
 
 
1、sql*loader的組成
 
1.命令
sqlldr user/password errors=n control='/xx/xx/xx/xx.ctl'  log='/xx/xx.log' bad='/xx/xx.bad'
--errors:容許失敗的最大行數,默認50。超過errors sqlldr自動中止。
--control:控制文件
--log:日誌,不指定也可,默認在執行sqlldr命令所在的目錄。
--bad:記錄導入失敗的數據,默認在執行sqlldr命令所在的目錄。
 
 
2.平面文件
平面文件中存放有規律的數據,好比以","逗號做爲列之間的分割,各列以雙引號""包圍。
以下:
"2012-06-25 00:03:01","5D8969C289594C4FE76188066C4D72C4","official","newwap","boutique_product","0","140","x39x0xxx89x3x","S60V52","45"
 
 
3.控制文件.ctl
也就是上面命令中的control=。控制文件時平面文件與數據庫表之間的橋樑。控制文件指定平面文件各列對應表中的哪些列。
如:
load data
CHARACTERSET UTF8
infile '/home/oracle/test_action.txt'
append into table scott.test_p2sp
fields terminated by ","
optionally enclosed by '"'
(LOG_TIME date "yyyy-mm-dd hh24:mi:ss",MD5ID,CHANNEL,SUB_CHANNEL,ACTION_TYPE,STATUS,VER,IMEI,MBL,PRODUCT_ID )
 
2、經常使用參數
sqlldr help=y能夠查看全部參數
 
DIRECT:直接路徑加載,它直接將數據寫入到database block中,大大加速了導入速度。默認值是false。使用direct=true,表中的觸發器失效。 
PARALLEL:並行加載。默認值是false。
rows:多少行提交一次
bindsize:每次提交記錄(依據rows參數)的緩衝區的大小,默認255420 bytes,通常設置爲20971520(20M),目前還沒測出最大值。與rows配合使用。在conventional path load(通常方式)下有效。bindsize制約rows,若是rows提交的數據,
即 行*行長>bindsize,那麼仍是以bindsize爲準。因此增大rows,必定要考慮bindsize是否夠用。
readsize:讀取緩衝區的大小 (默認 1048576),通常設置成20971520(20M)。readsize負責讀,而bindsize負責提交。若是readsize小於bindsize,那麼readsize會自動增長。
 
 
3、加速導入
1.表改成nologging
執行sqlldr命令以前,最好把相關表的logging模式改成nologging,這樣會減小redo日誌產生,同時也就加速了導入的速度。導完後再改成logging模式。
alter table table_name nologging;
alter table table_name logging;
 
2.PARALLEL
在命令中加入parallel=true
並行技術
 
3.DIRECT
使用direct path load(直接路徑加載),觸發器會失效。
有效的約束有:
NOT NULL
UNIQUE
PRIMARY KEY (unique-constraints on not-null columns)
失效的約束:
CHECK constraints
Referential constraints (FOREIGN KEY)
 
固然,也能夠parallel=true+direct=true
 
4.rows
rows=n,導入n行提交一次。
 
5.bindsize:
和rows結合使用,決定一次提交的行數。
 
6.readsize
 
 
 
4、控制文件參數
load data
CHARACTERSET UTF8
infile '/home/oracle/test_action.txt'
append into table scott.test_p2sp
fields terminated by ","
optionally enclosed by '"'
(LOG_TIME date "yyyy-mm-dd hh24:mi:ss",MD5ID,CHANNEL,SUB_CHANNEL,ACTION_TYPE,STATUS,VER,IMEI,MBL,PRODUCT_ID )
 
 
以上面爲例:
1.CHARACTERSET :字符集,如UTF8 
infile 平面文件所在位置,這裏能夠寫多個infile,也就是多個平面文件導入到一張表裏
infile '/home/oracle/1.csv'
infile '/home/oracle/2.csv'
 
2.xx into table:append into --追加
                  truncate into --把表的數據都刪除,而後導入
                  insert into --空表能夠採用insert
 
3.fields terminated by "," :以逗號做爲分隔
4.optionally enclosed by '"':列被雙引號包圍
 
5.函數
(1)日期轉換:平面文件中
"2012-06-25 00:03:01",
那麼ctl中,要根據平面文件日期格式在ctl中標明
LOG_TIME date "yyyy-mm-dd hh24:mi:ss",
 
(2)upper,轉成大寫
格式:col1 "upper(:col1)"
如:ACTION_TYPE "upper(:action_type)"
 
 
若是表中某列的類型爲varchar2(300),那麼在ctl中就要寫成char(300)
 
SQLLDR默認輸入流爲數據類型爲CHAR 長度爲 255 因此當 begindata section裏面的 輸入流 長於255 的時候會報錯的
 
 
5、sqllder的兩種方式
Direct path load和conventional path load。
從這裏能夠明顯看出Direct path load 與(經常使用方式)的區別
1.Conventional Path Load
使用sql insert方式插入數據。
特色:
(1)適用表中含有索引
(2)適用簇表:load data to a clustered table。direct path load不支持load data to  a clustered table簇表。
(3)知足全部約束constraint,如索引、not null等。
(5)你想知道哪些數據被rejected,信息記錄在sqlldr的log和bad文件中。
(6)觸發表中觸發器
(7)在插入時,別的用戶能夠操做該表
 
2.Direct Path Load
直接把數據寫到database block中,效率比Conventional Path Load高得多。Direct Path Load不通過oracle的sql這一層,也沒有parseing、executing這些過程,對於oracle數據庫的整個負載都是一個減輕。插入數據時,只是在表的HWM之上直接從新分配新的數據塊,而不是在freelist中查找能夠insert 的塊。
注意:direct path load方式也會產生redo,由於插入數據時會分配新extend,oracle必須記錄這些redo信息。
特色:
(1)direct path load不是知足全部的constraint,只知足primary key、unique、not null
(2)不能插入cluster table
(3)direct path load,在插入時,別的用戶不能操做該表(不能進行DML操做,不能創建、重建索引,甚至查詢)
(4)不會觸發觸發器
(5)適用於將大量數據導入到空表或者非空表,這個表最好不要含有觸發器、參考約束。
 
 
 
 
Conventional Path Load(傳統導入)優化實驗:
1.rows=10000,10000行提交一次
$ sqlldr scott/tiger errors=1000000 control='/home/oracle/test_action.ctl' rows=10000
##Space allocated for bind array:                 255420 bytes(99 rows)
##Elapsed time was:     00:03:05.90
#這裏rows=10000,而實際是99 rows提交一次,緣由在於bindsize<設置的rows*行長,因此採用默認的bindsize爲準。解決辦法:加大bindsize。
 
2.rows=10000,10000行提交一次,加大bindsize
$ sqlldr scott/tiger errors=1000000 control='/home/oracle/test_action.ctl' rows=10000 bindsize=20971520
##Space allocated for bind array:               20970240 bytes(8128 rows) //依然bindsize<設置的rows*行長
##Elapsed time was:    // 00:00:52.51 效率大大提升
#提示specified value for readsize(1048576) less than bindsize(20971520)
解決辦法:能夠忽略,或者設置readsize和bindsize等值(意義不大,當readsize<bindsize時,oracle會自動增大readsize)。
 
3.rows=10000,10000行提交一次,繼續加大bindsize
$ sqlldr scott/tiger errors=1000000 control='/home/oracle/test_action.ctl' rows=10000 bindsize=25800000 
##Space allocated for bind array:               25800000 bytes(10000 rows)//終於能夠一次提交10000行數據了
##Elapsed time was:     00:00:50.37  // 增大bindsize後,效果有所提升
 
4.row=10000,10000行提交一次,添加readsize
$ sqlldr scott/tiger errors=1000000 control='/home/oracle/p2sp_action.ctl' rows=10000 readsize=25800000 bindsize=25800000 
##Space allocated for bind array:               25800000 bytes(10000 rows)
##Elapsed time was:     00:00:49.49 //添加readsize參數後,效率有所提升
 
5.rows=10000,10000行提交一次,添加parallel=true
$ sqlldr scott/tiger errors=1000000 control='/home/oracle/test_action.ctl' rows=10000 readsize=25800000 bindsize=25800000  parallel=true
##Space allocated for bind array:               25800000 bytes(10000 rows)
##Elapsed time was:     00:00:48.86 //效率又提升了
 
總結:rows+bindsize+readsize是傳統導入最優方案。
 
 
Direct Path load實驗:
$ sqlldr scott/tiger@67 errors=1000000 control='/home/oracle/test_action.ctl' direct=true 
##Elapsed time was:     00:00:06.54//速度驚人啊!
 
 
 
遠程sqlldr導入數據
在A服務器上有csv文件,要導入到B庫中
 
 
 
用sqlldr+tnsnames.ora就能夠實現
 
1.首先要在A服務器安裝oracle client,client版本最好和DB版本相同
若是A服務器沒有oracle DB,那麼安裝oracle client來得到sqlldr命令,安裝的時候選擇自定義安裝,選擇oracle database utilties和oracle net兩項便可。
 
2.A庫配置tnsnames.ora
# tnsnames.ora Network Configuration File: /u01/app/product/11.1.0/client/network/admin/tnsnames.ora
# Generated by Oracle configuration tools.
B =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 172.16.0.67)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SID = hou)
    )
  )
 
 
3.A服務器上執行sqlldr命令,csv數據和ctl控制文件都在A服務器
$ sqlldr scott/tiger@67 errors=10 control='/home/oracle/test.ctl'
 
我試了一下optionally enclosed by '"'左邊沒引號右邊有引號:成功,原樣導入111"222""333"""左邊有引號右邊沒引號:失敗, second enclosure string not present"44""555"""666左右有相等的奇數個引號,成功,引號數=2n+1時導入數據帶有n個引號"777""""888"""左右有相等的偶數個引號,失敗, no terminator found after TERMINATED and ENCLOSED field""999""""""AAA""""一邊奇數一邊偶數:失敗, 錯誤信息爲上述兩種"BBB""""CCC""""DDD""""EEE"""兩邊不等的偶數:失敗, no terminator found after TERMINATED and ENCLOSED field""FFF""""""""GGG""兩邊不等的奇數:成功,引號數=2n+1時導入數據帶有n個引號"HHH""""""III"總結:要麼左邊不能帶引號;若是有引號左右都必須爲奇數個
相關文章
相關標籤/搜索