最近在做项目的时候,有要把txt文件导入到数据库,txt文件有千万级,如果使用传统的读文件,写数据库,效率很慢。自己按照这种方式使用100万条数据的txt文件导入到oracle数据库,花费了二十多分钟。针对这种情况,可使用sqlLoader方式加载。
数据说明:
文件名:abc.txt
文件格式如下:
1111111|1|20171025|100|1|2|3|
1111111|2|20171025|100|1|2|3|
1111111|3|20171025|100|1|2|3|
一、导入oracle数据库
shell如下:
String str="sqlldr "+用户名+"/"+密码+" control="+ctl文件路径+"import_clientinfo.ctl"+" log=log.log bad=bad.log errors=100000 rows=100000";
import_clientinfo.ctl文件内容如下:
load data
infile '
abc.txt'
append into table tbclientcrmbranchno
fields terminated by '|'
(
IN_CLIENT_NO,
CLIENT_NO,
TRANS_DATE,
BRANCH_NO,
RESERVE1,
RESERVE2,
RESERVE3
)
解释说明:
infile '
abc.txt' 表示要导入的文本文件名为
abc.txt
append into table 后接要导入的表名
此处用append表示追加到表中,若用
Insert 表示导入空表,有数据则停止;
Replace表示原来表中如果有数据,则会被删除(用delete from table语句)
Truncate表示原来表中如果有数据,则会被清除(用truncate table语句)
fields terminated by '|' 数据中每行记录用”|”分隔
java程序调用shell:Process pro = Runtime.getRuntime().exec(str);
pro.waitFor();
如果数据量大,此时会发生阻塞,导致数据不能全部插入到oracle数据库,但是程序还在运行,如果关掉服务器,这时候,文件中的数据会全部导入到oracle数据库。
此时处理缓冲区中的信息,开两个线程分别去处理标准输出流和错误输出流。
程序如下:
package com.hundsun.base.database; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; public class ManyNumImport { public static void main(String[] args) { String str="sqlldr 用户名/密码 controlctl文件路径import_clientinfo.ctl" +" log=log.log bad=bad.log errors=100000 rows=100000"; Process pro = null; try { pro = Runtime.getRuntime().exec(str); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } printMessage(pro .getInputStream()); printMessage(pro .getErrorStream()); try { pro.waitFor(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } private static void printMessage(InputStream inputStream) { new Thread(new Runnable() { public void run() { Reader reader = new InputStreamReader(inputStream); BufferedReader bf = new BufferedReader(reader); String line = null; try { while((line=bf.readLine())!=null) { System.out.println(line); } } catch (IOException e) { e.printStackTrace(); } } }).start(); } }
二、导入db2数据库
data_finalasset.sh如下:
#shell脚本传入参数校验
if [ $# -ne 3 ] ; then
echo "data_finalasset.sh 脚本传入参数错误"
echo "Usage: data_finalasset.sh 数据库用户 用户密码 数据文件存放路径"
exit 1
fi
#数据库实例名根据现场情况配置
echo "导入数据准备开始"
db2 connect to ifm30as user $1 using $2;
db2 "import from $3 of del modified by coldel| nodoubledel replace into tbargfinalasset(client_no,trans_date,month,final_assets)"
db2 connect reset
db2 quit
echo "导入数据准备完成"
说明:
ifm30as 表述数据库名称;
$1:用户名
$2:密码
$3:文件名称
coldel|:表示使用"|"分割
java程序如下:
String shellDir = 路径+ "data_finalasset.sh " +用户名 + " " + 密码+ " " + 'abc.txt'; Process pro = ScriptExec.exec1("sh "+shellDir); String line = ""; input = new BufferedReader(new InputStreamReader(pro .getInputStream())); errorInput = new BufferedReader(new InputStreamReader(pro .getErrorStream())); while ((line = errorInput.readLine()) != null) {// 判断执行脚本时有没有发生错误。 LcptLog.getTransLogNoCache().fatal(line); } while ((line = input.readLine()) != null) { BatchLog.writeLog(context, line); // shell脚本执行结果输出到备份日志文件中 } pro.waitFor();