最近正在作一個項目,須要導出數據庫中的表,可是數據庫中有不少帶有虛擬列的表,並且表中的數據很是的龐大,有些表中的數據上億條,項目經理讓我研究如何快速導出這些數據。linux
下面是我研究的一些經歷:sql
(1)、我先使用plsql developer導出dmp(其實是經過emp導出),可是不能導出帶有虛擬列的表,導出的速度有點慢;數據庫
(2)、使用plsql developer自帶的導出功能,如圖所示:windows
該方法能夠導出虛擬列,可是導出的速度很慢,比dmp還慢,大約是方法(1)的2倍時間。oracle
(3)、使用數據泵 DataPump導出,該方法能夠導出虛擬列,並且速度還能夠,可是若是導出遠程庫數據的時候,須要用dblink,並且須要很高的權限(至關於dba的權限),因此該方法也被排除。app
一、軟件下載地址:測試
百度雲連接:https://pan.baidu.com/s/1V8eqyyYsbJqQSD-Sn-RQGg
提取碼:6mdn
spa
下載完後並解壓會生成4個文件操作系統
sqluldr2.exe 用於32位windows平臺; 3d
sqluldr2_linux32_10204.bin 適用於linux32位操做系統;
sqluldr2_linux64_10204.bin 適用於linux64位操做系統;
sqluldr264.exe 用於64位windows平臺。
二、直接在cmd上運行(個人sqluldr文件放在H盤裏,我電腦是64位,因此使用sqluldr264)
首先,你必須安裝oracle,沒有安裝oracle,sqluldr2不能運行,運行完後出現以下的界面,這樣就證實能夠成功運行。
user=用戶名/密碼@ip地址:1521/服務 ,若是是本地庫,能夠只寫 用戶名和密碼:eg:user=用戶名/密碼
query=」sql查詢語句」
head=yes|no 是否導出表頭
file=文件存放路徑(該文件能夠寫不少後綴: .txt .csv .dmp 等等,我發現,導出.dmp文件速度快)
table=查詢的表名 有這句話,sqluldr2會自動生成一個.ctl文件,導入的時候會用到();
Field:分隔符,指定字段分隔符,默認爲逗號; 好比:field=# 在選擇分隔符時,必定不能選擇會在字段值中出現的字符組合,如常見的單詞等,不少次導入時報錯,回過頭來找緣由時,都發現是由於分隔符出如今字段值中了。
record:分隔符,指定記錄分隔符,默認爲回車換行,Windows下的換行;
quote:引號符,指定非數字字段先後的引號符;
charset:字符集,執行導出時的字符集,通常有UTF八、GBK等;
sqluldr264 user=zxx/zxx123@127.0.0.1:1521/orcl query="select * from mv_xlsymx1 where ysyddm='00001H'" head=yes file=h:\mx.csv log=+h:\tem.log
可使用sql參數代替query
sqluldr264 user=zxx/zxx sql=h:\test.sql head=yes file=h:\mx.csv
test.sql是提早維護好的一個文件,文件的內容爲sql語句。
sqluldr264 user=zxx/zxx query="select * from mv_xlsymx1 where ysyddm='00001H'" table=mv_xlsymx1 head=yes file=h:\mx.csv
它會生成一個.ctl文件(mv_xlsymx1_sqlldr.ctl,默認生成在sqluldr文件下,個人就生成在h:\sqluldr\ mv_xlsymx1_sqlldr.ctl)
sqluldr264 user=zxx/zxx query="select * from mv_xlsymx1 where ysyddm='00001H'" table=mv_xlsymx1 control=h:\mx.ctl head=yes file=h:\mx.csv
當集成sqluldr2在腳本中時,就但願屏蔽上不輸出這些信息,但又但願這些信息能保留,這時能夠用「LOG」選項來指定日誌文件名。
sqluldr264 user=zxx/zxx query="select * from mv_xlsymx1 where ysyddm='00001H'" head=yes file=h:\mx.csv log=+h:\tmp.log
注意:這裏的log路徑要寫上「+」
characterset :字符集, 通常使用字符集 AL32UTF8,若是出現中文字符集亂碼時,改爲 ZHS16GBK。
fields terminated by 'string':文本列分隔符。當爲tab鍵時,改爲'\t',或者 X'09';空格分隔符 whitespace,換行分隔符 '\n' 或者 X'0A';回車分隔符 '\r' 或者 X'0D';默認爲'\t'。
optionally enclosed by 'char':字段包括符。當爲 ' ' 時,不把字段包括在任何引號符號中;當爲 "'" 時,字段包括在單引號中;當爲'"'時,字段在包括雙引號中;默認不使用引用符。
fields escaped by 'char':轉義字符,默認爲'\'。
trailing nullcols:表字段沒有對應的值時,容許爲空。
append into table "T_USER_CTRL" -- 操做類型
-- 1) insert into --爲缺省方式,在數據裝載開始時要求表爲空
-- 2) append into --在表中追加新記錄
-- 3) replace into --刪除舊記錄(至關於delete from table 語句),替換成新裝載的記錄
-- 4) truncate into --刪除舊記錄(至關於 truncate table 語句),替換成新裝載的記錄skip=1 :表示插入數據時,跳過第一行(標題),從第二行開始導入;
sqlldr userid=hxj/hxj control=h:\sqluldr\mv_xlsymx1_sqlldr.ctl data=h:\mx.csv rows=1000
若是是本地庫,能夠直接只用 用戶名/密碼;
若是是遠程庫,須要將userid寫全 userid=用戶名/密碼@ip:1521/服務名
好比:userid=zxx/zxx123@10.3.36.110:1521/orcl,填寫本身遠程庫地址
sqlldr userid=hxj/hxj control=h:\sqluldr\mv_xlsymx1_sqlldr.ctl data=h:\mx.csv log=h:\log\mx.log rows=1000
注意:這裏的log的路徑不能寫「+」;
sqluldr2導出數據的時候,若是該表中含有虛擬列,你導出的時候沒有過濾掉虛擬列,好比:select * from 帶有虛擬列的表,那麼你要對這些虛擬列進行處理,不然導入的時候回報錯。
我發現了三種處理方法:
好比,不寫select * from 表名
直接將不是虛擬列的列名寫出來 select id,name from 表名
sqlldr userid=hxj/hxj control=h:\ctl\qsddlqymx1_cyqs.ctl data=h:\qsddlqymx1_cyqs.dmp log=h:\log\qsddlqymx1_cyqs.log
1567258條數據大概須要 一分半
須要在導入語句中加入 direct=true parallel=true,以下所示:
sqlldr userid=hxj/hxj control=h:\ctl\qsddlqymx1_cyqs.ctl data=h:\qsddlqymx1_cyqs.dmp log=h:\log\qsddlqymx1_cyqs.log direct=true parallel=true
並行能更快的導入數據,1567258條數據大概20秒,可是有缺點(我測試的時候發現的,可能有別的解決方法)
(1):首先.ctl文件必須是append into table 表名;
(2):須要導入的表不能有索引。
這是我寫的第一篇博客,望看客老爺們多多指教。