日期:2014-05-16  浏览次数:20423 次

hibernate 作批量数据操作心得

?

程序功能:
使用hibernate+spring将oracle数据库中的tfile表中的数据抽取到db2数据库的tfile表,这两个表的结构相同。(原本要使用一些Spring的特性,但是程序改来改去发现Spring特性一个都没用上,实际上完全可以由hibernate创建两个sessionFactory完成)
测试环境:
celeron M 1.4/512M/mysql 5.0数据库
代码:

?public void save() {

  Session session= fileDAO.getDataSession();
  Session session2= fileDAO2.getDataSession();
  Transaction tx =session2.beginTransaction();
  int count=0;
  List list =fileDAO.getList(session, count);
  while(list.size()!=0)
  {
   for(int i=0,num =list.size();i<num;i++)
   {
    session2.save(list.get(i));
    session.evict(list.get(i));
    if(num%50==0)
    {
     session2.flush();
     session2.clear();
    }
   }
   count= count+500;
   list =fileDAO.getList(session, count);
   
  // System.out.println(count);
   
  }
  tx.commit();
  session.close();
  session2.close();
}

?配置文件:


<prop key="hibernate.cache.use_second_level_cache">false</prop>
<prop key="hibernate.jdbc.batch_size">50</prop>

?1、为保证不会出现内存溢出
?? hibernate.jdbc.batch_size 设为 20-50
?? 并在代码中没隔50个insert后手工清理数据?
if(num%50==0)

    {
     session2.flush();
     session2.clear();
    }

?2、为保证减少二级缓存导致的过多的内存开销关,闭二级缓存
??hibernate.cache.use_second_level_cache 设为false
3、保证使用长事务,不要在每个插入都事务提交,这样性能可以有很大幅度的提升(由于原先配的事务没有正常运行,在初次测试时此程序插入4万条数据用了12分钟,使用了长事务后仅为34秒)
4、使用ScrollableResults(提供了数据库的游标特性)然后插入的效果好像要优于分批抓取分批插入的效果,(4万条数据,用ScrollableResult耗时29秒)但网上有人声称批量抓取插入的效果要好可能在远程数据库的情况下批量抓取的可靠性更高一点的原因。这一点我询问过公司里做数据库比较好的人,批量处理数据是要使用游标处理的。就游标而言分为动态游标,静态游标,动态游标慢于静态游标,静态游标慢于静态查询,但是如果用分批抓取数据的话就涉及到数据分段截取,为保证每次分段截取时数据的正确性,应该要预先对数据处理,所以批量抽取数据的速度可能会慢一些。以下为使用ScrollableResult的程序
Session session= fileDAO.getDataSession();

  Session session2= fileDAO2.getDataSession();
  Transaction tx =session2.beginTransaction();
  ScrollableResults tFiles = session.createQuery(
    "from TFile as model ").setCacheMode(CacheMode.IGNORE).scroll(ScrollMode.FORWARD_ONLY);
  int count=0;
  while(tFiles.next())
  {
   session2.save(tFiles.get(0));
   if(++count%50==0)
    {
     session2.flush();
     session2.clear();
    }
  }
  tx.commit();
  session.close();
?

?