(1)使用mybatis的foreach语法:
private static void listinsert() {
EjsonDecoder el = new EjsonDecoder().unbare();
List<Map> list=new ArrayList<Map>();
SqlSession session=SqlSessionUtil.sf.openSession();
long start=System.currentTimeMillis();
for(int logid=1;logid<=60000;logid++){
String msg="{appCode:nihao,apptx:zzc2017021401,bizkey:CS-007,channelId:18b0kw8,city:510,methodCode:crck,province:51,reqTs:1492152950566,txid:"+ ("123456789"+logid) + "}";
Map log=el.decode(msg);
list.add(log);
if(logid%10==0){
session.insert("dao.DemoDao.insertAopTradeForReq",list);
session.commit();
session.clearCache();
session.close();
session=SqlSessionUtil.sf.openSession();
list=new ArrayList<Map>();
}
}
System.out.println("60万条耗时 :"+(System.currentTimeMillis()-start));
}
对应的 SQL语句:
<insert id="insertAopTradeForReq" >
insert into AOP_TRADE (
LOG_ID,
APPCODE,
BIZKEY ,
METHODCODE,
APPTX,
PROVINCE,
CITY,
CHANNEL_ID,
REQTIMES,
UPDATE_TIME
)
<foreach collection="list" item="item" index="index" separator="union all" >
(select
#{item.txid,jdbcType=VARCHAR},
#{item.appCode,jdbcType=VARCHAR},
#{item.bizkey,jdbcType=VARCHAR},
#{item.methodCode,jdbcType=VARCHAR},
#{item.apptx,jdbcType=VARCHAR},
#{item.province,jdbcType=VARCHAR},
#{item.city,jdbcType=VARCHAR},
#{item.channelId,jdbcType=VARCHAR},
#{item.reqTs,jdbcType=NUMERIC},
sysdate
from dual)
</foreach>
</insert>
这时:批量在list中存入10条,100条,1000条耗时分别是 54917毫秒,27949毫秒,25446毫秒。
(2)使用事务批量提交:
private static void onebyone() {
EjsonDecoder el = new EjsonDecoder().unbare();
//List<Map> list=new ArrayList<Map>();
SqlSession session=SqlSessionUtil.sf.openSession(ExecutorType.BATCH,false);
long start=System.currentTimeMillis();
for(int logid=1;logid<=60000;logid++){
String msg="{appCode:nihao,apptx:zzc2017021401,bizkey:CS-007,channelId:18b0kw8,city:510,methodCode:crck,province:51,reqTs:1492152950566,txid:"+ ("123456789"+logid) + "}";
// if(logid==1199)
// msg="{appCode:nihaonihaonihaonihaonihao,apptx:zzc2017021401,bizkey:CS-007,channelId:18b0kw8,city:510,methodCode:crck,province:51,reqTs:1492152950566,txid:"+ ("123456789"+logid) + "}";
// if(logid==7199)
// msg="{appCode:nihaonihaonihaonihaonihao,apptx:zzc2017021401,bizkey:CS-007,channelId:18b0kw8,city:510,methodCode:crck,province:51,reqTs:1492152950566,txid:"+ ("123456789"+logid) + "}";
Map log=el.decode(msg);
session.insert("dao.DemoDao.insertAopTradeTest", log);
//list.add(log);
if(logid%5000==0){
session.commit();
session.clearCache();
session.close();
session=SqlSessionUtil.sf.openSession(ExecutorType.BATCH,false);
//list=new ArrayList<Map>();
}
}
System.out.println("60万条耗时 :"+(System.currentTimeMillis()-start));
}
这时采用5000条,10000条,20000条,30000条插入提交一次,分别耗时5798毫秒,4526毫秒,4976毫秒,4707毫秒。
(3)采用上面两者结合:
private static void combine() {
EjsonDecoder el = new EjsonDecoder().unbare();
List<Map> list=new ArrayList<Map>();
SqlSession session=SqlSessionUtil.sf.openSession(ExecutorType.BATCH,false);
long start=System.currentTimeMillis();
for(int logid=1;logid<=60000;logid++){
String msg="{appCode:nihao,apptx:zzc2017021401,bizkey:CS-007,channelId:18b0kw8,city:510,methodCode:crck,province:51,reqTs:1492152950566,txid:"+ ("123456789"+logid) + "}";
Map log=el.decode(msg);
list.add(log);
if(logid%100==0){
session.insert("dao.DemoDao.insertAopTradeForReq",list);
if(logid%5000==0){
session.commit();
session.clearCache();
session.close();
session=SqlSessionUtil.sf.openSession(ExecutorType.BATCH,false);
}
list=new ArrayList<Map>();
}
}
System.out.println("60万条耗时 :"+(System.currentTimeMillis()-start));
}
实验结果为:
list存10条,100次insert提交一次:9107毫秒
list存10条,1000次insert提交一次:9034毫秒
list存100条,50次insert提交一次:8776毫秒
综上所述: 采用第二种大的方案较好。
但是涉及到批量数据提交,都要保证这些数据中没有错误数据,都可以插入到数据库中,否则根据事务原理,全都成功,或全部都不成功。这样对于安全性不高的数据差如有很高的风险,这里采用增加错误日志表的方法:
1,创建对应的错误日志表(sql语句):
BEGIN -- 为 aop_business 创建一个 名字为
DBMS_ERRLOG.CREATE_ERROR_LOG('aop_trade', 'aop_trade_ERROR_LOG');
END;
2,在执行sql时加上:
insert into aop_trade values( a1,a2,a3,a4) LOG ERRORS INTO AOP_TRADE_ERROR_LOG REJECT LIMIT UNLIMITED
后面的多出来的便可以解决事务中有错误数据的情况。