hibernate 批量数据插入 mysql

Aschrius 发布于 2014/11/26 21:18
阅读 6K+
收藏 1

之前有一个也是关于hibernate大数据处理的一些问题,还没有找到答案,大家有兴趣可以去看看。别答非所问啊。

好吧,今天问一个Hibernate大批量数据插入的问题。

前些日子又遇到一个问题。

解析csv文件,
插入数据库,
直接使用session.createSQLQuery()的原生sql插入:insert into 
大致6W条数据,用了2min。表没有外键关联。

然后问了下,被告知,速度还是很慢,要求去网上找些sql数据库批量插入数据优化的方法。

于是度娘之,测试之,可惜都没有有效的方法。

所以我又来求助了,请问有啥优化的方法嘛?

加载中
1
triankg
triankg

 mysql sql  支持 

 insert into tableName values(..),(..); 

 合并为一条插入语句 


 
Aschrius
Aschrius
这个要拼装很长的字符串,故不采用。
0
优雅先生
优雅先生

尝试用下Hibernate的Batch Insert(参考http://www.tutorialspoint.com/hibernate/hibernate_batch_processing.htm):

Session session = SessionFactory.openSession();
Transaction tx = session.beginTransaction();
for ( int i=0; i<100000; i++ ) {
    Employee employee = new Employee(.....);
    session.save(employee);
	if( i % 50 == 0 ) { // Same as the JDBC batch size
        //flush a batch of inserts and release memory:
        session.flush();
        session.clear();
    }
}
tx.commit();
session.close();
然后还需要在配置文件中配置下hibernate.jdbc.batch_size,它的值与上面的值相等:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM 
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
   <session-factory>
   <property name="hibernate.dialect">
      org.hibernate.dialect.MySQLDialect
   </property>
   <property name="hibernate.connection.driver_class">
      com.mysql.jdbc.Driver
   </property>

   <!-- Assume students is the database name -->
   <property name="hibernate.connection.url">
      jdbc:mysql://localhost/test
   </property>
   <property name="hibernate.connection.username">
      root
   </property>
   <property name="hibernate.connection.password">
      root123
   </property>
   <property name="hibernate.jdbc.batch_size">
      50
   </property>

   <!-- List of XML mapping files -->
   <mapping resource="Employee.hbm.xml"/>

</session-factory>
</hibernate-configuration>

Aschrius
Aschrius
也试过了:-(
优雅先生
优雅先生
回复 @生吃番茄酱 : 那你不要用原生的sql试试呗
Aschrius
Aschrius
这个方法一直在用,不过我这里用的是session.createSQLQuery()原生的sql,hibernate不管理他的缓存的╮(╯-╰)╭
0
francis-x
francis-x
批处理插入,多进程插入。这注定是个耗时的操作,可以考虑整个程序的设计,比如插入操作改为异步。
Aschrius
Aschrius
异步插入。。 。。事务应该如何管理?
0
魔力猫
魔力猫

首先你要确定一件事,那就是这个操作可接受的时间到底是多少,为什么高于这个时间就无法接受。不能随口就说2分钟导入慢,得说为什么无法接受2分钟导入。有了这个,才能确认方案以及成本。

其次,分析你现在的代码,确认到底是哪里消耗最大。是生成SQL还是数据库执行。

第三,MySQL本身有导入csv的能力,如果格式不需要大改,那么可以考虑直接将csv传到mysql可以访问的一个目录,然后用数据库内部命令来解决。

刚才还找到一篇博客,可以mysql jdbc还支持直接导入本地csv。http://blog.csdn.net/chris830/article/details/2660899

0
首席打酱油
首席打酱油

getHibernateTemplate().saveOrUpdateAll(List<T>)  你可以试下这个方法

不行的话用这个,mysql源生的批处理

   String sql = "insert into user_user values(?,?)";
               PreparedStatement statement = connection.prepareStatement(sql);
               for(;;){
                
                        stmt.setString(1, p.resource.id);
stmt.setInt(2, role_id);
stmt.setString(3, p.operation);
stmt.setString(4, type);
stmt.addBatch();
                 }
           stmt.executeBatch();

0
九千里
九千里

插入6W条数据... 你直接在数据库中执行插入6W条数据的语句都需要两分钟吧?

如果在数据库中插入不需要这么久,还是创建个存储过程来调用好了。。。

返回顶部
顶部