最近正在作一个项目,须要导出数据库中的表,可是数据库中有不少带有虚拟列的表,并且表中的数据很是的庞大,有些表中的数据上亿条,项目经理让我研究如何快速导出这些数据。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):须要导入的表不能有索引。
这是我写的第一篇博客,望看客老爷们多多指教。