1. 程式人生 > >oracle 外部表使用詳解

oracle 外部表使用詳解

外部表,相對於資料庫內部表來說的,意思是將作業系統檔案作為一個數據庫,資料從檔案而來。
我把它理解成類似指標的東西,告訴使用者,這個表的資料是從哪些檔案來的。

外部表的建立,這裡寫的比網上其他介紹複雜許多,簡單的用法,自行百度,這裡只考慮 多檔案
大資料、每行資料沒有分隔符,欄位靠擷取、外部白匯入型別是oracle loader的條件。網上的
一些文章只做了一些簡單的介紹和用法,只能滿足簡單的需求,而真是需要使用到外部表的一半都
是上百萬級別的大資料。先看看基本語法,裡面的引數將會一一詳解。

語法如下:

create table "table1" 
(
    id varchar2(4
), name varchar2(20) )ORGANIZATION external --外部表的關鍵字 ( type oracle_loader --外部表有兩種型別,這裡使用oracle_loader DEFAULT DIRECTORY DATA_FILE_PATH --檔案目錄 ACCESS PARAMETERS( --引數 RECORDS DELIMITED BY NEWLINE CHARACTERSET ZHS16GBK SKIP 10 BADFILE 'DATA_LOG_PATH':'table1.bad'
NODISCARDFILE LOGFILE 'DATA_LOG_PATH':'table1.log' READSIZE 1048576 FIELDS LDRTRIM REJECT ROWS WITH ALL NULL FIELDS ( "id" (1,4) char(4) nullif ("id" = blanks), "name" (5,24) char(20) nullif ("name" = blanks) ) ) location ( test1.txt, test2.txt )REJECT LIMIT UNLIMITED;

使用外部表需要注意一下幾點:
1、資料檔案(test1.txt,test2.txt)的存放路徑必須是資料庫伺服器能夠訪問到的地方
這點非常關鍵,許多產品一半是資料庫伺服器跟應用後臺分離的方式,所以,這就要求檔案能
夠放在資料庫伺服器上,而不是後臺伺服器,或者兩者之間加一塊共享儲存,這裡兩臺都能訪
問。

2、建立外部表之前,需要先建立目錄物件DATA_FILE_PATH,也就是,資料檔案需要放在這
個目錄物件中,也就是,這個目錄物件的路徑,是資料庫伺服器上的路徑。建立語法如下:

CREATE OR REPLACE DIRECTORY IMPORT_DATA_FILE_PATH AS '/home/file'

由於上面的例子我把生成的log、bad檔案單獨存放,所以建立兩個目錄。

3、執行建立外表語句 ,可以在oracle客戶端執行,且建立表不載入資料,也就是資料如果有錯,
或者檔案不存在,不會報錯,建立是成功的,只有當insert到正式表時,才是載入資料的過程。

4、外部表只能查詢,不能做DML操作,外部表只能查詢,不能做DML操作,外部表只能查詢,
不能做DML操作,重要的事情說3遍。外部表只能當作中間工具,建立好外部表時,使用
insert into 正式表 select * from 外部表;
載入資料到正式表中。這個過程可以使用查詢並行和DML並行,提升載入效能(這裡有坑,後面
解釋)。

現在來講講外部表的一些引數

1、TYPE 外部表的型別,有兩種,一種是oralce_loader,一種是ORACLE_DATAPUMP,後者
沒用過,也講不來,自行百度。oralce_loader型別,就可以把外部表當作多個sqlldr,如果沒有
瞭解過sqlldr,可以先了解一下,比較外部表的本質還是這個。具體有多少個sqlldr呢,差不多
location裡面有多少個檔案,就有多少個sqlldr,所以,使用外部表匯入大資料,效能會比一個
sqlldr好得多。

2、DEFAULT DIRECTORY 就是指定目錄物件,檔案一定要在這裡面!!!

3、RECORDS DELIMITED BY NEWLINE CHARACTERSET ZHS16GBK 指定資料庫的字符集,
資料庫字符集可以查詢出來。
select userenv(‘language’) from dual;

4、BADFILE 指定bad檔案存在路徑,什麼是bad檔案,就是資料裡面,違反了欄位規則的資料
,就會被當中bad資料放到裡面。如果不需要生成,則寫NOBADFILE.

5、DISCARDFILE 丟棄的檔案,跟bad檔案不一樣,這個是違反了篩選條件的資料,上面的例
子沒寫,這裡寫下:

SKIP 10
BADFILE 'DATA_LOG_PATH':'table1.bad' 
NODISCARDFILE
LOGFILE 'DATA_LOG_PATH':'table1.log'
LOAD WHEN ("id" != blanks)

6、LOAD WHEN 載入條件,結合上面說,就是篩選條件,這裡面的寫法只能指定欄位的值,不
能限制類型,而且語法限制條件也很多,sql的函式不能用,只能使用and or = != 這些。上面
DISCARDFILE ,就是如果不滿足這個load when,則這行資料將會被丟棄,放到你指定的檔案中
去,如果不需要生成,則NODISCARDFILE。
回過來說這個load when ,寫法也很多,可以指定欄位,也可以指定長度,比如:
load when (1:20) != blanks,就是說,從1到20個字元不能是空白。這個load when官方文件也
說的很少,具體的用法,需要自己慢慢摸索。

7、SKIP N 跳過,顧名思義,載入資料時候告訴Oracle跳過多少行,這裡挺坑,一個數據檔案,
跳過沒問題,如果有多個數據檔案,它只能跳過第一個檔案的n行,這不坑爹嗎?還有,上面說
insert到正式表的可以使用並行,注意!!!!!SKIP,只能在非並行模式下使用!!!!!!!
如果需要使用並行DML或者查詢,麻煩把這個引數去掉!!!!!

8、READSIZE 1048576 這個是指定一次性讀取最大值。

9、FIELDS LDRTRIM 載入的時候,每個欄位都要trim一下

10、REJECT ROWS WITH ALL NULL FIELDS 就是說如果欄位沒有資料,則為null

11、欄位規則,很簡單,如果是有分隔符的寫法,網上很多,這裡模擬的資料是沒有分隔符的,
類似於這樣:
132334342354656546646454564564564564535242
“id” (1,4) char(4) nullif (“id” = blanks) 分別是欄位名,擷取起始位置,型別和長度,條件是
如果為空格則欄位為Null。這裡是字串型別的,如果是number型別的欄位,條件這麼寫:
“age” (21,23) INTEGER EXTERNAL(3)

12、location 裡面就是需要載入的檔名字

13、REJECT LIMIT UNLIMITED 預設是有限制的載入,這裡設定的是無限制載入。

外部表的引數太多了,有一些沒用過,也不知道怎麼用,有興趣的,可以去oracle官方文件裡面
慢慢看,全英文的。

外部表的效率,還是非常可觀的,500W資料,使用sqlldr匯入的話,需要大概8-10分鐘載入完,
如果使用外部,開了並行,1分鐘搞定。