sqlldr使用
# ctl_jpf.ctl
load data
infile 'jpf01.csv'
insert into table TEST_BUD_SN_ID
fields terminated by ','
TRAILING NULLCOLS
(
SN,
TEST_ID
)
# insert :默认方式,在导入记录前要求表为空;
# append :在表中追加新导入的记录;表不为空时需要追加数据
# replace :删除旧记录(等价delete from table语句),替换成新导入的记录;
# truncate:删除旧记录(等价truncate table语句),替换成新导入的记录;
# into table后面指定导入数据库表USER_INFO,
sed -i 's/jpf11/jpf12/g' ctl_jpf.ctl
sed -i 's/insert/append/g' ctl_jpf.ctl
sqlldr userid=IMES_T/'xxxxxx' control=ctl_jpf.ctl data=jpf12.csv log=jpflog.log bad=jpfbad.bad errors=99999999
sqlldr userid=IMES_T/'xxxxxx' control=test.ctl data=test.txt log=test.log bad=test.bad errors=99999999
# test.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')")
sqlldr userid=yuwen/xxxxxx control=loaddata_USER_INFO_direct.ctl direct=true
direct=true ,options中的BINDSIZE换成了COLUMNARRAYROWS,因为BINDSIZE是常规路径绑定数组的大小,而COLUMNARRAYROWS是直接路径列数组的行数。
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')")
https://www.jianshu.com/p/498c26ba95a7
Usage: SQLLDR keyword=value [,keyword=value,...]
部分关键字:
userid -- ORACLE username/password
control -- 控制文件
log -- 记录的日志文件
bad -- 坏数据文件
data -- 数据文件
discard -- 丢弃的数据文件
discardmax -- 允许丢弃数据的最大值 (默认全部)
skip -- Number of logical records to skip (默认0)
load -- Number of logical records to load (默认全部)
errors -- 允许的错误记录数 (默认50)
rows --(每次提交的记录数,如每2000条提交一次。默认: 常规路径 64, 直接路径 全部,所以使用直接路径的话,效率会比普通的好太多太多)
bindsize --( 每次提交记录的缓冲区的大小,字节为单位,默认256000)
silent -- 禁止输出信息 (header,feedback,errors,discards,partitions)
direct -- 使用直通路径方式导入 (默认FALSE)
parfile -- parameter file: name of file that contains parameter specifications。参数文件:包含参数说明的文件的名称
parallel -- 并行导入(默认FALSE,并行方式仅仅在direct=true方式时有效,并行方式只支持append导入。注意:parallel并不是让一个sqlldr语句起多个进程来加载数据,而是不锁住加载表,允许别的直接路径加载. 所以要使parallel起作用,应该先将要加载的数据文件分成多个,用多个sqlldr语句同时加载,如下例:
skip_unusable_indexes -- disallow/allow unusable indexes or index partitions(默认FALSE),不允许/允许使用无用的索引(默认FALSE)
skip_index_maintenance -- do not maintain indexes, mark affected indexes as unusable(默认FALSE,这个最好设置为TRUE)。不维护索引,将受到影响的索引标记为失效(默认FALSE)
file -- file to allocate extents from 要从以下对象中分配区的文件
commit_discontinued -- commit loaded rows when load is discontinued (默认 FALSE)。提交加载中断时已加载的行(默认FALSE)
readsize -- size of read buffer (默认 1048576)。读取缓冲区的大小 (默认1048576)
external_table -- use external table for load; NOT_USED, GENERATE_ONLY, EXECUTE (默认 NOT_USED)。使用外部表进行加栽:NOT_USED,GENERATE_ONLY,EXECUTE (默认 NOT_USED)
columnarrayrows -- number of rows for direct path column array (默认 5000)。直接路径列数组的行数(默认5000)
streamsize -- size of direct path stream buffer in bytes (默认 256000)。直接路径流缓冲区的大小(默认256000,单位字节)
multithreading -- use multithreading in direct path。在直接路径中使用多线程
resumable -- enable or disable resumable for current session (默认 FALSE)。启用或禁用当前的可恢复会话(默认FALSE)
resumable_name -- text string to help identify resumable statement。有助于标识可恢复语句的文本字符串
resumable_timeout -- wait time (in seconds) for RESUMABLE (默认 7200)。RESUMABLE 的等待时间(以秒计)(默认 7200)
date_cache -- size (in entries) of date conversion cache (默认 1000)。日期转换高速缓存的大小(以条目计)(默认1000)
LOAD DATA INFILE "users_data.csv"--指定外部数据文件,可以写多个 INFILE "another_data_file.csv" 指定多个数据文件--这里还可以使用 BADFILE、DISCARDFILE 来指定坏数据和丢弃数据--的文件,
truncate --操作类型,用 truncate table 来清除表中原有记录
INTO TABLE users -- 要插入记录的表
Fields terminated by ","-- 数据中每行记录用 "," 分隔
Optionally enclosed by '"' -- 数据中每个字段用 '"' 框起,比如字段中有 "," 分隔符时
trailing nullcols --表的字段没有对应的值时允许为空
(
virtual_column FILLER, --这是一个虚拟字段,用来跳过由 PL/SQL Developer 生成的第一列序号
user_id number, --字段可以指定类型,否则认为是 CHARACTER 类型, log 文件中有显示
user_name,
login_times,
last_login DATE"YYYY-MM-DD HH24:MI:SS"-- 指定接受日期的格式,相当用 to_date() 函数转换
)
0) 配置文件
************* 以下是4种装入表的方式
APPEND // 原先的表有数据 就加在后面
INSERT // 装载空表 如果原先的表有数据 sqlloader会停止 默认值
REPLACE // 原先的表有数据 原先的数据会全部删除
TRUNCATE // 指定的内容和replace的相同 会用truncate语句删除现存数据
*************
import.ctl(含序列,不能设direct=true):
load data
infile '/home/oracle/data/import.dat'
append
into table sys_login_records_detail_1
fields terminated by ','
(
LOGIN_DATE DATE "yyyy-mm-dd" TERMINATED BY whitespace,
FILLER_1 FILLER,
GAME_ID,
FILLER_2 FILLER,
IP,
MAC,
NETBAR_ID,
PROVINCE,
CITY,
LOGIN_TIMES,
id POSITION(1:1) "sys_login_records_detail_seq_1.nextval" ---序列
)
import.ctl(不含序列,可设direct=true):
Load data
infile '/home/oracle/data/import.dat'
append
into table sys_login_records_detail_1
fields terminated by ','
(
LOGIN_DATE DATE "yyyy-mm-dd" TERMINATED BY whitespace,
FILLER_1 FILLER,
GAME_ID,
FILLER_2 FILLER,
IP,
MAC,
NETBAR_ID,
PROVINCE,
CITY,
LOGIN_TIMES
)
1) 老例 导入
sqlldr user/xxxxxx control=/home/oracle/data/install.ctl
log=/home/oracle/data/export.log
bad=/home/oracle/data/export.bad
##Space allocated for bind array: 132352 bytes(64 rows)
##Elapsed time was: 00:01:45.85
2) 1000条提交一次
sqlldr user/password control=/home/oracle/data/install.ctl
log=/home/oracle/data/export.log
bad=/home/oracle/data/export.bad
rows=1000 readsize=2068000 bindsize=2068000
##Space allocated for bind array: 2068000 bytes(1000 rows)
##Elapsed time was: 00:00:22.80
3) 10000条提交一次
sqlldr user/password@dbname
control=/home/oracle/data/install.ctl
log=/home/oracle/data/export.log
bad=/home/oracle/data/export.bad
rows=10000 readsize=20680000 bindsize=20680000
##Space allocated for bind array: 20680000 bytes(10000 rows)
##Elapsed time was: 00:00:20.25
4) 设置direct=true, 含序列
sqlldr user/password@dbname
control=/home/oracle/data/install.ctl
log=/home/oracle/data/export.log
bad=/home/oracle/data/export.bad
direct=true
##ORA-01400: cannot insert NULL into ("EMOA"."sys_login_records_detail_1"."ID")
5) 设置direct=true, 去掉序列字段, 最快的行动
#SQL> alter table emoa.sys_login_records_detail_1 drop column id;
sqlldr user/password@dbname
control=/home/oracle/data/export.ctl
log=/home/oracle/data/export.log
bad=/home/oracle/data/export.bad
direct=true
##Elapsed time was: 00:00:10.98
##但是假如 有频频数据, 会把唯一索引置为unusable, 要确保数据源已剔重
6) 设置readsize和bindsize到最大值, 高效又稳妥的行动 , 终极 回收 方案
sqlldr user/password@dbname
control=/home/oracle/data/export.ctl
log=/home/oracle/data/export.log
bad=/home/oracle/data/export.bad
rows=100160 readsize=20971520 bindsize=20971520 PARALLEL=TRUE
##Space allocated for bind array: 20970240 bytes(10160 rows)
##Elapsed time was: 00:00:14.36
提高 SQL*Loader 的性能
1) 一个简单而容易忽略的问题是,没有对导入的表使用任何索引和/或约束(主键)。如果这样做,甚至在使用ROWS=参数时,会很明显降低数据库导入性能。
2) 可以添加 DIRECT=TRUE来提高导入数据的性能。当然,在很多情况下,不能使用此参数。
3) 通过指定 UNRECOVERABLE选项,可以关闭数据库的日志。这个选项只能和 direct 一起使用。
4) 可以同时运行多个导入任务。
常规导入与direct导入方式的区别
常规导入可以通过使用 INSERT语句来导入数据。Direct导入可以跳过数据库的相关逻辑(DIRECT=TRUE),而直接将数据导入到数据文件中。
1.direct对性能的影响是巨大的,如果为Fasle(默认值),1万的记录需要100秒,太慢了,后来设置为TRUE,配合其他的设置,200万的记录,330秒搞定,这个速度和MySQL中的select ....into的效率差不多,应该还算很不错的了。不过由于我在Oracle中
对大对象进行了压缩,所以需要10分钟
2.如果表中有索引的话,是不能指定direct=TRUE的,除非使用skip_index_maintenance=TRUE,这个就是在导入的时候忽略索引,所以在数据导入完毕以后,查看索引的状态应该都是无效的,需要重建之,如下SQL语句
select * from dba_indexes where table_name='?'
alter idnex index_name rebuild
不过在我测试过程中,这种方式是比较合理的,重建索引比新建索引要快很多,如我200W的记录,重建主键只需1分钟多,新建的话则要7分钟。
3.在数据导入的过程,让该表不记录日志,数据库不开启归档日志
alter database noarchivelog
alter table BLOG nologging
--End--
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。