Hibernate/MySQL 批量插入问题

6
我有困难让Hibernate在MySQL上执行批量插入。
我使用的是Hibernate 3.3和MySQL 5.1。
在高层次上,情况如下:
@Transactional
public Set<Long> doUpdate(Project project, IRepository externalSource) {
    List<IEntity> entities = externalSource.loadEntites();
    buildEntities(entities, project);
    persistEntities(project);
}
public void persistEntities(Project project) {
     projectDAO.update(project);
}

这将导致 n 个日志条目(每行一个)如下所示:

Hibernate: insert into ProjectEntity (name, parent_id, path, project_id, state, type) values (?, ?, ?, ?, ?, ?)

我希望看到这个操作被批处理,以便更新更高效。这个例程可能会生成成千上万行,而每行都需要与数据库交互是一种性能杀手。
为什么没有进行批处理呢?(我的理解是,在适当的情况下,Hibernate 应该默认使用批量插入)。
3个回答

7

Pascal的回答是正确的。然而,因为您正在使用MySQL,我也强烈建议您尝试在JDBC URL中使用rewriteBatchedStatements=true参数。

这个参数会使JDBC驱动程序动态地重写您的INSERT批处理,以使用单个“多值”INSERT,例如:

INSERT INTO mytable (mycol) VALUES (0);
INSERT INTO mytable (mycol) VALUES (1);
INSERT INTO mytable (mycol) VALUES (2);

将被重写为:

INSERT INTO mytable (mycol) VALUES (0), VALUES (1), VALUES (2);

这在某些情况下可能会有重大的差异。查看http://www.jroller.com/mmatthews/entry/speeding_up_batch_inserts_for获取一些示例测量数据。


6

第13章 批处理所述:

If you are undertaking batch processing you will need to enable the use of JDBC batching. This is absolutely essential if you want to achieve optimal performance. Set the JDBC batch size to a reasonable number (10-50, for example):

hibernate.jdbc.batch_size 20

Hibernate disables insert batching at the JDBC level transparently if you use an identity identifier generator.

不要忘记定期flushclear会话,否则将会像13.1. 批量插入文档中所述的那样出现OutOfMemoryException

但是,在处理成千上万行数据时,建议考虑使用StatelessSession接口


这会使SQL语句批处理吗?(无论会话是否保留状态,听起来与批处理相当正交,但也许我从类名中推断得太多了) - meriton
关于标识符生成器的部分有点晦涩 - 这个帖子对此进行了解释:https://forum.hibernate.org/viewtopic.php?p=2436697 - Mike Baranczak

0
Pascal 在 Hibernate 上做得非常好。作为替代方案,您可以使用 JDBC 模板的 Batchsqlupdate。但是,我必须警告您,Hibernate 缓存的实例可能无法反映使用上述方法进行的更改。在我们的项目中,我们不得不采取预防措施来克服这个问题,通过创建一个不同的计划表(另一个问题被创建了,但在我们的控制范围内)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接