关于批量存储数据的一点体会

  场景是这样的,一个List中有至少一万个Bean,有时会有八万以上的Bean,将这个List插入到数据库中,如果用Hibernate的话,最简单的办法就是for循环然后挨个插入,顶多到一定批次flush掉session。

  还有一种做法就是通过多线程的方式,将这几万个bean分成若干份然后每一份启动一个线程进行插入操作。

  我采用的是第二种做法,在DAO内实现一个线程池,然后调用多线程来完成插入操作。

  来看看伪代码:

   public Long[] saveXXXBatch(List<Bean> beans,Integer batchSize) {
// TODO Auto-generated method stub
if(batchSize==null){
batchSize=1000;
}

                //batchSize就是批次数,每插入这么多个bean就可以flush一次


final Session session=sessionFactory.getCurrentSession();

Integer beanSize=beans.size();
List<Long> ids=new ArrayList<Long>();
if(beanSize<batchSize){
for(Bean bean:beans){
session.save(bean);
}

                 //如果要插入的bean数小于批次数,那么就直接插入
}else{
Integer batchCount=(beanSize%batchSize==0?(beanSize/batchSize):(beanSize/batchSize+1));

                        //这个是计算要分几批插入
ExecutorService es=Executors.newFixedThreadPool(batchCount);

                       //起一个线程池,池子的大小就是上面计算的次数的多少
for(int i=0;i<batchCount;i++){
int beginIndex=i*batchSize;
int endIndex=0;
if(i==batchCount-1){
endIndex=beanSize-1;
}else{
endIndex=(i+1)*batchSize-1;
}
final List<Bean> subBeans=beans.subList(beginIndex, endIndex);

                                然后截取这个List
Future<Long[]> f=es.submit(new Callable(){

@Override
public Object call() throws Exception {
// TODO Auto-generated method stub

                                                       for(Bean bean:subBeans){

                                                       session.save(bean);

                                                       }

session.flush();
return XXX;
}
return null;
}

});

}

                       //然后就是启动多线程进行插入操作
if(!es.isShutdown()){
es.shutdown();
}

                       //最后关闭线程池
}
return null;
}

当然我用了Callable和Future是因为插入后要返回一些数据,返回数据的过程也有一点耗时,但这段程序对比传统的直接for循环全部插入还是能省一点时间的。

当然我测试的网络环境不稳定以及Callable里有耗时操作也造成一定影响,测试结果不一定很准,但确实是多线程的插入方式平均时间短。

希望大家能一起探讨!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值