excel导入oracle数据库,特别慢,求优化的解决办法?

时间:2022-09-20 16:35:13
     我现在做的程序思路,是先把excel写到web服务器上的固定目录下,然后再通过jxl来循环把excel中的数据一条一条导入的Oracle数据库中。
     我的excel为从运营商处导出的话单,有14列,现在一个excel话单有1000调记录,我导入到数据库中大概要40分钟的,太慢了,求有没有好的导入方法啊。

     以下为导入的部分代码
//读取Excel文件中第一个工作簿中的数据
jxl.Sheet rs = excelWorkBook.getSheet(0);
lengthOfWorkBook = rs.getRows();

Map columnMap = new HashMap();
for(int i=0;i<column.size();i++){
columnMap.put((String)column.get(i), new Integer(i));
}

String sqlForQuery = "select * from z_tellistmx a left join z_tellist b on a.nlist_sn=b.nlist_sn " +
"where rtrim(a.sdhhm)=? and (rtrim(a.sdfhm)=? or a.sdfhm is null) and rtrim(b.sajbh)=? " +
"and to_char(a.dhjrq, 'yyyy-MM-ddHH24:mi:ss')=?";
String sqlForInsert = " insert into z_tellistmx (nlist_sn, nhdxh, shdly, sdhhm, sthbs, szbjbs, sdfhm, dhjrq, nthsc, " +
"syhdd, sdfdd, ssbbh, sxqbh, sdqbh,sbz1,sbz2,sbz3) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?,?,?)";

String shdly;//话单来源
String sdhhm;//电话号码
String sthbs;//通话标识
String szbjbs;//主被叫标识
String sdfhm;//对方号码
String syhdd;//用户号码通话所在地
String sdfdd;//对方号码归属地
String ssbbh;//设备号
String slac_o = "";//基站LAC--未区分进制
String sid_o ="";//基站ID--未区分进制
String sbz1 ="";//备注1
String sbz2="";
String sbz3="";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date dhjrq;
String dhjrqs ="";
String dhjsj = "";
String nhdxh = "";
String nthsc = "";
//根据工作簿中的数据做相应处理
///默认:0序号@、1话单来源@、2电话号码、3通话标识@、4主被叫标识@、5对方号码、6呼叫日期、7呼叫时间@、8通话时长
//9用户号码通话所在地、10对方号码归属地、11设备号、12基站LAC、13基站ID--14
String[] strArray={"", "", "", "", "", "", "", "", "", "", "", "", "", ""};
for(indexOfRow=1;indexOfRow<lengthOfWorkBook;indexOfRow++){//循环处理数据,第一行为表头,不做处理
for(int indexOfCol = 0; indexOfCol <strArray.length; indexOfCol++){//获取单元格中的数据值
Cell c = rs.getCell(indexOfCol, indexOfRow);
strArray[indexOfCol]= c.getContents().trim();//c.getContents()不会为null值
}
System.out.println("columnMap="+columnMap.toString());
String array = "";
for(int i=0;i<strArray.length-1;i++)
{
    array += String.valueOf(strArray[i])+",";   
}  


shdly = (columnMap.get("shdly")==null?" ":strArray[((Integer)columnMap.get("shdly")).intValue()]);
sdhhm = (columnMap.get("sdhhm")==null?" ":strArray[((Integer)columnMap.get("sdhhm")).intValue()]);
sthbs = (columnMap.get("sthbs")==null?" ":strArray[((Integer)columnMap.get("sthbs")).intValue()]);
szbjbs = (columnMap.get("szbjbs")==null?" ":strArray[((Integer)columnMap.get("szbjbs")).intValue()]);
sdfhm = (columnMap.get("sdfhm")==null?" ":strArray[((Integer)columnMap.get("sdfhm")).intValue()]);
syhdd = (columnMap.get("syhdd")==null?" ":strArray[((Integer)columnMap.get("syhdd")).intValue()]);
sdfdd = (columnMap.get("sdfdd")==null?" ":strArray[((Integer)columnMap.get("sdfdd")).intValue()]);
ssbbh = (columnMap.get("ssbbh")==null?" ":strArray[((Integer)columnMap.get("ssbbh")).intValue()]);
slac_o = (columnMap.get("sdqbh")==null?" ":strArray[((Integer)columnMap.get("sdqbh")).intValue()]);
sid_o = (columnMap.get("sxqbh")==null?" ":strArray[((Integer)columnMap.get("sxqbh")).intValue()]);
sbz1 = (columnMap.get("sbz1")==null?" ":strArray[((Integer)columnMap.get("sbz1")).intValue()]);
sbz2 = (columnMap.get("sbz2")==null?" ":strArray[((Integer)columnMap.get("sbz2")).intValue()]);
sbz3 = (columnMap.get("sbz3")==null?" ":strArray[((Integer)columnMap.get("sbz3")).intValue()]);
dhjrqs = (columnMap.get("dhjrq")==null?" ":strArray[((Integer)columnMap.get("dhjrq")).intValue()]);
dhjsj = (columnMap.get("dhjsj")==null?" ":strArray[((Integer)columnMap.get("dhjsj")).intValue()]);
nhdxh  = (columnMap.get("nhdxh")==null?" ":strArray[((Integer)columnMap.get("nhdxh")).intValue()]);
nthsc  = (columnMap.get("nthsc")==null?"0":strArray[((Integer)columnMap.get("nthsc")).intValue()]);//通话时长int型

//判断dhjrqs是否为4位
if (!dhjrqs.substring(0, 2).equals("20")) {
dhjrqs = "20" + dhjrqs;
}
System.out.println("通话日期:"+dhjrqs+" "+dhjsj);


if(!stelhm.equals(sdhhm))
throw new Exception("号码不一致");

if( shdly.length()==2 &&!sdhhm.equals("") &&!sdfhm.equals("") ){//判断数据有效性:话单来源、电话号码、对方号码
validCount++;
if(JT.queryForList(sqlForQuery, new Object[]{sdhhm, sdfhm, sajbh, //判断 电话号码、对方号码、案件编号、呼叫日期、呼叫时长是否同时已经存在
dhjrqs + 
dhjsj}).size()==0){//如果表中不存在此通话记录
shdly = (String)provType.get(shdly);//运营商标识
shdly = shdly==null?"99":shdly;
sdhhm = sdhhm.length()>30 ? sdhhm.substring(0, 30):sdhhm;
sthbs = (String)callType.get(sthbs);//通话标识
sthbs = sthbs==null?"99":sthbs;
szbjbs = szbjbs.equals("主叫")?"1":"2";//主被叫标识
sdfhm = sdfhm.length()>30 ? sdfhm.substring(0, 30):sdfhm;
//sdfhm.replace("12593", "").replace("17951", "").replace("11808", "");
    if(dhjrqs.equals(" ")||dhjsj.equals(" ")){
     dhjrq = new Date(); // 不确定
    }else{
dhjrq = sdf.parse( dhjrqs + " " +
     dhjsj );
    }
    
    if(syhdd.length()>=2 && !syhdd.startsWith("0"))
     syhdd = "0"+syhdd;
    if(sdfdd.length()>=2 && !sdfdd.startsWith("0"))
     sdfdd = "0"+sdfdd;
    
    
    if(slac_o.length()<5){
     int laclen = slac_o.length();
for(int i=0;i<5-laclen;i++)
slac_o ="0"+slac_o;
}
    if(sid_o.length()<5){
     int idlen = sid_o.length();
for(int i=0;i<5-idlen;i++)
sid_o ="0"+sid_o;
}
   
    
    
    ssbbh = ssbbh.length()>30 ? ssbbh.substring(0, 30):ssbbh;
    slac_o = slac_o.length()>10 ? slac_o.substring(0, 10):slac_o;
    sid_o = sid_o.length()>10 ? sid_o.substring(0, 10):sid_o;
    sbz1 = sbz1.length()>100 ? sbz1.substring(0, 100):sbz1;
    sbz2 = sbz2.length()>100 ? sbz2.substring(0, 100):sbz2;
    sbz3 = sbz3.length()>100 ? sbz3.substring(0, 100):sbz3;
    String slac, sid;
if(system.equals("d")){//十进制
slac = slac_o;
sid = sid_o;
}else{//十六进制
slac = Integer.toString(Integer.parseInt(slac_o, 16));
int laclenth = slac.length();
if(slac.length()<5){
for(int i=0;i<5-laclenth;i++)
slac ="0"+slac;
}
sid = Integer.toString(Integer.parseInt(sid_o, 16));
int idlenth = sid.length();
if(sid.length()<5){
for(int i=0;i<5-idlenth;i++)
sid ="0"+sid;
}
}
    
// int status=JT.update(sqlForInsert, new Object[]{nlist_sn, strArray[((Integer)columnMap.get("nhdxh")).intValue()], shdly, sdhhm, sthbs, szbjbs, 
// sdfhm, dhjrq, strArray[((Integer)columnMap.get("nthsc")).intValue()], syhdd, sdfdd, ssbbh, slac, sid});
int status=JT.update(sqlForInsert, new Object[]{nlist_sn, nhdxh, shdly, sdhhm, sthbs, szbjbs, 
sdfhm, dhjrq, nthsc, syhdd, sdfdd, ssbbh, sid, slac,sbz1,sbz2,sbz3});
if(status==1){//序号必须有
succCount++;
System.out.println("第"+indexOfRow+"条导入成功!");
}else{
System.out.println("第"+indexOfRow+"条导入失败!");
}
}else{//如果表中存在此通话记录
repeatCount++;
System.out.println("第"+indexOfRow+"条重复,不导入!");
}
}else{
System.out.println("第"+indexOfRow+"条因话单来源/电话号码/对方号码为空,无法导入!");
}
}

3 个解决方案

#1


不要 每一条 的 读取 插入, 读取 插入
 最好 一次性 读取 一部分 比如 1000条,然后 一次性插入,这样 IO开销 要小得多 

#2


我觉得JXL得到1000条数据,不会很慢。
慢可能是你调用了一千次的数据库连接。不能在java Dao里面
循环1000次,执行插入语句 insert xxxx  into xxxx .
你可以写个存储过程,一次性读入100条数据。用分隔符分开来。
然后在存储过程里面循环100次,每次执行一个 inert xxxxx into xxxx 。然后每100条记录统一commit 。
这样应该会很快的。

#3


或者用长度为100的数组传给存储过程。 

#1


不要 每一条 的 读取 插入, 读取 插入
 最好 一次性 读取 一部分 比如 1000条,然后 一次性插入,这样 IO开销 要小得多 

#2


我觉得JXL得到1000条数据,不会很慢。
慢可能是你调用了一千次的数据库连接。不能在java Dao里面
循环1000次,执行插入语句 insert xxxx  into xxxx .
你可以写个存储过程,一次性读入100条数据。用分隔符分开来。
然后在存储过程里面循环100次,每次执行一个 inert xxxxx into xxxx 。然后每100条记录统一commit 。
这样应该会很快的。

#3


或者用长度为100的数组传给存储过程。