Oracle數據庫導入csv文件(sqlldr命令行)


1.說明

Oracle數據庫導入csv文件,
當csv文件較小時,
可以使用數據庫管理工具,
比如DBevaer導入到數據庫,
當csv文件很大時,
可以使用Oracle提供的sqlldr命令行工具,
能夠快速導入大量數據。
在數據庫之間進行數據遷移時,
特別是不同類型的數據庫,
使用csv文件是一種很好的選擇。

2.sqlldr用法

下面介紹sqlldr用法,
有一個USER_INFO.csv文件,
需要導入到數據庫中USER_INFO表,
而且有1.5億條數據,
要求導入耗時盡量小。
這里先介紹基本的導入方式,
然后介紹direct導入方式,
最后介紹parallel導入方式。

3.獲取csv文件

USER_INFO.csv文件內容如下,
這里僅選取了三條測試數據:

MSISDN,PROVINCE_CODE,CREATE_TIME
8617512570551,30,2019-10-31 17:16:09
8613063310680,33,2019-10-31 17:16:12
8613295281345,80,2019-10-31 17:16:14

4.創建USER_INFO表

CREATE TABLE "USER_INFO" ( 
"MSISDN" VARCHAR2(16),
"PROVINCE_CODE" VARCHAR2(4),
"CREATE_TIME"   DATE,
CONSTRAINT "PK_USER_INFO_MSISDN" PRIMARY KEY ("MSISDN") 
) TABLESPACE "USERS";

COMMENT ON COLUMN "USER_INFO"."MSISDN" IS '用戶手機號';
COMMENT ON COLUMN "USER_INFO"."PROVINCE_CODE" IS '省份編碼'; 
COMMENT ON COLUMN "USER_INFO"."CREATE_TIME" IS '用戶創建時間'; 

注意表中字段要和csv文件對應。

5.創建ctl文件

創建名為loaddata_USER_INFO.ctl的控制文件:

options(skip=1,BINDSIZE=20971520, ROWS=10000, READSIZE=20971520, ERRORS=999999999)
load data
infile '/home/oracle/USER_INFO.csv'
insert into table "USER_INFO"
fields terminated by ','  
Optionally enclosed by '\''  
(MSISDN,PROVINCE_CODE,CREATE_TIME "to_date(:CREATE_TIME, 'yyyy-mm-dd hh24:mi:ss')")

第1行是導入參數配置,
已經是支持大量數據導入的參數方案。

第3行infile指定導入的文件是USER_INFO.csv;

第4行into table前面的insert表示導入方式:

  1. insert :默認方式,在導入記錄前要求表為空;
  2. append :在表中追加新導入的記錄;
  3. replace :刪除舊記錄(等價delete from table語句),替換成新導入的記錄;
  4. truncate:刪除舊記錄(等價truncate table語句),替換成新導入的記錄;
    into table后面指定導入數據庫表USER_INFO,
    且表名必須大寫;

第5行指定每一行的字段是以逗號(,)分隔;

第6行指定字段是用兩個分號(')包圍起來的,可選的;

最后一行對應導入的字段,
注意如果導入的是時間字段,
需要指明時間轉換的格式。

6.使用sqlldr導入

指定需要導入的數據庫,
以及使用的control文件:

sqlldr userid=yuwen/ai123456@10.21.13.14:1521/orcl control=loaddata_USER_INFO.ctl

導入成功輸出日志如下:

SQL*Loader: Release 12.1.0.2.0 - Production on Thu Oct 31 17:37:49 2019

Copyright (c) 1982, 2014, Oracle and/or its affiliates.  All rights reserved.

Path used:      Conventional
Commit point reached - logical record count 3

Table "USER_INFO":
  3 Rows successfully loaded.

Check the log file:
  loaddata_USER_INFO.log
for more information about the load.

看到3條數據成功導入USER_INFO,
同時會生成loaddata_USER_INFO.log日志,
通過該日志可以查看更詳細的導入信息,
如果導入時發生錯誤,
可以查看到詳細的錯誤信息,
而且還會生成USER_INFO.bad文件,
bad文件原樣輸出了導入失敗的數據。
默認情況下ERRORS達到50個就會停止導入,
如果需要忽略錯誤繼續導入,
可以配置ERRORS最大值為999999999。

7.direct直接路徑方式

sqlldr支持direct參數,
使用直接路徑方式導效率非常高,
direct參數默認為FALSE,
上面第6步使用的就是默認常規路徑方式,
下面使用直接路徑方式,
進一步加快數據導入速度。
但是使用直接路徑方式會導致表的唯一索引(或主鍵)失效,
可以在導入前先刪除表的唯一索引,
然后在導入完成后重建索引即可,
如果有重復的數據,
需要先去重才能重建索引成功,
經過測試即使需要重建索引,
使用直接路徑方式還是比常規路徑方式快。

8.創建ctl文件(直接路徑方式)

創建名為loaddata_USER_INFO_direct.ctl的控制文件:

options(skip=1,COLUMNARRAYROWS=20971520, ROWS=10000, READSIZE=20971520, ERRORS=999999999)
load data
infile '/home/oracle/USER_INFO.csv'
insert into table "USER_INFO"
fields terminated by ','  
Optionally enclosed by '\''  
(MSISDN,PROVINCE_CODE,CREATE_TIME "to_date(:CREATE_TIME, 'yyyy-mm-dd hh24:mi:ss')")

這個文件和第5步中的區別在於,
options中的BINDSIZE換成了COLUMNARRAYROWS,
因為BINDSIZE是常規路徑綁定數組的大小,
而COLUMNARRAYROWS是直接路徑列數組的行數。

9.刪除主鍵

導入前需要先刪除USER_INFO表的主鍵:

ALTER TABLE USER_INFO DROP CONSTRAINT PK_USER_INFO_MSISDN;

10.使用sqlldr導入(直接路徑方式)

基本與第6步的命令相同,增加direct=true:

sqlldr userid=yuwen/ai123456@10.21.13.14:1521/orcl control=loaddata_USER_INFO_direct.ctl direct=true

數據成功導入日志如下:

SQL*Loader: Release 12.1.0.2.0 - Production on Fri Nov 1 10:48:10 2019

Copyright (c) 1982, 2014, Oracle and/or its affiliates.  All rights reserved.

Path used:      Direct

Load completed - logical record count 3.

Table "USER_INFO":
  3 Rows successfully loaded.

Check the log file:
  loaddata_USER_INFO_direct.log
for more information about the load.

11.重建主鍵

ALTER TABLE USER_INFO ADD CONSTRAINT PK_USER_INFO_MSISDN PRIMARY KEY(MSISDN);

至此使用直接路徑方式導入數據成功,
經過測試1.5億條不重復數據direct方式導入,
花費4分02秒,
然后重建主鍵花費19分14秒,
總耗時23分16秒。
然而使用常規路徑方式導入需要48個小時,
導入效率得到了極大的提升。

12.parallel並行導入

前面使用的是串行方式導入數據,
通過設置parallel為true可以並行導入,
在多核服務器上面能進一步提升導入效率。
需要注意並行方式僅僅在直接路徑方式時有效。

13.創建ctl文件(並行方式)

創建名為loaddata_USER_INFO_direct_parallel.ctl的控制文件:

options(skip=1,COLUMNARRAYROWS=20971520, ROWS=10000, READSIZE=20971520, ERRORS=999999999)
load data
infile '/home/oracle/USER_INFO.csv'
append into table "USER_INFO"
fields terminated by ','  
Optionally enclosed by '\''  
(MSISDN,PROVINCE_CODE,CREATE_TIME "to_date(:CREATE_TIME, 'yyyy-mm-dd hh24:mi:ss')")

這個文件和第8步中的區別在於,
並行方式只支持append導入,
而且要注意USER_INFO表不能有索引,
如果有需要先刪除。

14.使用sqlldr導入(並行方式)

基本與第10步的命令相同,增加parallel=true:

sqlldr userid=yuwen/ai123456@10.21.13.14:1521/orcl control=loaddata_USER_INFO_direct_parallel.ctl direct=true parallel=true

數據成功導入日志如下:

SQL*Loader: Release 12.1.0.2.0 - Production on Fri Nov 1 11:08:51 2019

Copyright (c) 1982, 2014, Oracle and/or its affiliates.  All rights reserved.

Path used:      Direct
SQL*Loader-281: Warning: ROWS parameter ignored in parallel mode.

Load completed - logical record count 3.

Table "USER_INFO":
  3 Rows successfully loaded.

Check the log file:
  loaddata_USER_INFO_direct_parallel.log
for more information about the load.

15.sqlldr命令說明

15.1.用法

SQLLDR keyword=value [,keyword=value,...]

15.2.參數說明

參數 說明
userid ORACLE 用戶名/口令
control 控制文件名
log 日志文件名
bad 錯誤文件名
data 數據文件名
discard 廢棄文件名
discardmax 允許廢棄的文件的數目 (全部默認)
skip 要跳過的邏輯記錄的數目 (默認 0)
load 要加載的邏輯記錄的數目 (全部默認)
errors 允許的錯誤的數目 (默認 50)
rows 常規路徑綁定數組中或直接路徑保存數據間的行數,默認: 常規路徑 64, 所有直接路徑)
bindsize 常規路徑綁定數組的大小 (以字節計) (默認 256000)
silent 運行過程中隱藏消息 (標題,反饋,錯誤,廢棄,分區)
direct 使用直接路徑 (默認 FALSE)
parfile 參數文件: 包含參數說明的文件的名稱
parallel 執行並行加載 (默認 FALSE)
file 要從以下對象中分配區的文件
skip_unusable_indexes 不允許/允許使用無用的索引或索引分區 (默認 FALSE)
skip_index_maintenance 沒有維護索引, 將受到影響的索引標記為無用 (默認 FALSE)
commit_discontinued 提交加載中斷時已加載的行 (默認 FALSE)
readsize 讀取緩沖區的大小 (默認 1048576)
external_table 使用外部表進行加載; NOT_USED, GENERATE_ONLY, EXECUTE (默認 NOT_USED)
columnarrayrows 直接路徑列數組的行數 (默認 5000)
streamsize 直接路徑流緩沖區的大小 (以字節計) (默認 256000)
multithreading 在直接路徑中使用多線程
resumable 啟用或禁用當前的可恢復會話 (默認 FALSE)
resumable_name 有助於標識可恢復語句的文本字符串
resumable_timeout RESUMABLE 的等待時間 (以秒計) (默認 7200)
date_cache 日期轉換高速緩存的大小 (以條目計) (默認 1000)
no_index_errors 出現任何索引錯誤時中止加載 (默認 FALSE)

15.3.注意事項

命令行參數可以由位置或關鍵字指定。
前者的例子是 'sqlldr scott/tiger foo';
后這的例子是 'sqlldr control=foo userid=scott/tiger'。
位置指定參數的時間必須早於,
但不可遲於由關鍵字指定的參數。
例如允許 'sqlldr scott/tiger control=foo logfile=log',
但是不允許 'sqlldr scott/tiger control=foo log',
即使參數 'log' 的位置正確。

15.4.重要參數

rows:
加載的行數,默認值:常規路徑:64,直接路徑:全部。
常規路徑導入時,指定綁定數組中的行數。直
接路徑導入時,指一次從數據文件只讀取的行數。
該參數同時受bindsize制約,
如果rows每行實際占用大小超出bindsize的最大可用值,
則rows自動降低到bindsize最大可用值。

bindsize:
默認值:256000,以字節為單位。
為綁定數組指定最大可用空間,
用來存儲一次讀取的rows的記錄,
該值不能太小,至少要能放入一條邏輯記錄,
不然有可能造成加載失敗,
但是設置一個超大值也沒有意義,
浪費空間而且起不到任何效果。

direct:
直接路徑,默認值是false。
直接路徑加載並不是通過insert語句的方式提交數據,
直接路徑的加載甚至不走db_buffer,
因為不會存在緩沖區爭用,
直接路徑加載直接向數據文件寫數據,
因此效率較高。

file:
指定寫入的表空間數據文件。
通常是並行加載時應該會用到該參數,
指定file文件后,
要加載的內容即只向指定的數據文件寫入數據,
通過這種方式某些情況下可以減小磁盤間的競爭。

skip_unusable_indexes:
是否跳過不可用的索引,默認為false。
如果設置為true。在加載數據的時候,
如果沒加載的表中索引為unusable,
則該索引數據不維護,數據加載完以后也不會改變索引的狀態。
在oracle中也有一個參數叫skip_unusable_indexes,
但是sqlldr中的這個參數優先級比oracle數據庫內部的這個參數優先級高。
如果sqlldr中未設置這個參數,則以oracle中的skip_unusable_indexes參數為准。

skip_index_maintenance:
是否跳過索引維護,默認值為false。
該參數僅在直接路徑加載時有效,
如果設置為true,則數據加載過程中並不會維護索引,
因此數據加載完后會導致索引無效。

readsize:
緩沖區大小,默認值1048576字節,最大不超過20M。
該參數設置的值僅當從數據文件中讀取數據時有效,
如果數據包含在控制文件中則為64K,並不可修改。

streamsize:
流緩沖區大小,默認值是256000字節。
指定直接路徑加載時流緩沖區大小。

multithreading:
是否啟用多線程。
默認值:多cpu系統默認為true,單cpu的系統默認則為false。
該參數僅僅在直接路徑加載時有效。

date_cache:
日期轉換緩存,默認值為1000條。
指定一個專門用於日志轉換的緩存區,
如果處理的日期在其中,則不需要轉換,
否則直接取出來使用。

16.執行結果詳細日志

給出loaddata_USER_INFO_direct_parallel.log日志內容,
可以看到導入使用的配置,耗時等詳細信息,
供給大家參考:

SQL*Loader: Release 12.1.0.2.0 - Production on Fri Nov 1 11:20:07 2019

Copyright (c) 1982, 2014, Oracle and/or its affiliates.  All rights reserved.

Control File:   loaddata_USER_INFO_direct_parallel.ctl
Data File:      /home/oracle/USER_INFO.csv
  Bad File:     USER_INFO.bad
  Discard File:  none specified
 
 (Allow all discards)

Number to load: ALL
Number to skip: 1
Errors allowed: 999999999
Continuation:    none specified
Path used:      Direct - with parallel option.

Table "USER_INFO", loaded from every logical record.
Insert option in effect for this table: APPEND

   Column Name                  Position   Len  Term Encl Datatype
------------------------------ ---------- ----- ---- ---- ---------------------
MSISDN                              FIRST     *   ,  O(') CHARACTER            
PROVINCE_CODE                        NEXT     *   ,  O(') CHARACTER            
CREATE_TIME                          NEXT     *   ,  O(') CHARACTER            
    SQL string for column : "to_date(:CREATE_TIME, 'yyyy-mm-dd hh24:mi:ss')"

SQL*Loader-281: Warning: ROWS parameter ignored in parallel mode.


Table "USER_INFO":
  3 Rows successfully loaded.
  0 Rows not loaded due to data errors.
  0 Rows not loaded because all WHEN clauses were failed.
  0 Rows not loaded because all fields were null.

Bind array size not used in direct path.
Column array  rows :   10000
Stream buffer bytes:  256000
Read   buffer bytes:20971520

Total logical records skipped:          1
Total logical records read:             3
Total logical records rejected:         0
Total logical records discarded:        0
Total stream buffers loaded by SQL*Loader main thread:        1
Total stream buffers loaded by SQL*Loader load thread:        0

Run began on Fri Nov 01 11:20:07 2019
Run ended on Fri Nov 01 11:20:13 2019

Elapsed time was:     00:00:05.60
CPU time was:         00:00:00.44

17.參考文章

將CSV文件數據導入Oracle數據庫
(sqlldr)將xx.csv文件導入oracle數據庫
sqlldr總結參數介紹
Loading data in direct mode and unique index ORA-26026


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM