Hibernate/MySQL 批量插入问题

Posted

技术标签:

【中文标题】Hibernate/MySQL 批量插入问题【英文标题】:Hibernate / MySQL Bulk insert problem 【发布时间】:2011-01-19 04:14:43 【问题描述】:

我无法让 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 个日志条目(每行 1 个),如下所示:

Hibernate: 插入到 ProjectEntity (name, parent_id, 路径、project_id、状态、类型)值 (?, ?, ?, ?, ?, ?)

我希望看到这个被批处理,所以更新的性能更高。此例程可能会导致生成数万行,而每行的 db 行程是一个杀手。

为什么不进行批处理? (据我了解,hibernate 在适当的情况下应该默认批量插入)。

【问题讨论】:

【参考方案1】:

帕斯卡的回答是正确的。但是,由于您使用的是 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 获取一些示例测量值。

【讨论】:

【参考方案2】:

如Chapter 13. Batch processing 中所述:

如果您正在进行批处理 处理您需要启用 使用 JDBC 批处理。这是 如果您愿意,绝对必要 达到最佳性能。设置 JDBC 批量大小到一个合理的数量 (例如 10-50):

hibernate.jdbc.batch_size 20

Hibernate 禁用插入批处理 JDBC 级别是透明的,如果你 使用身份标识符生成器。

不要忘记定期flush 然后clear 会话,否则您将收到OutOfMemoryException,如13.1. Batch inserts 中所述。

但是 IMO,对于数万行,您应该考虑使用 the StatelessSession interface。

【讨论】:

这会启用 SQL 语句的批处理吗? (会话是否保持状态听起来与批处理相当正交,但也许我从类名推断得太多) 关于标识符生成器的部分有点神秘 - 这个线程解释它:forum.hibernate.org/viewtopic.php?p=2436697【参考方案3】:

Pascal 已经在休眠环境中很好地解决了这个问题。作为替代方案,您可以使用 jbdc 模板的 Batchsqlupdate。但是我必须警告您,休眠缓存实例可能无法反映使用上述所做的更改。在我们的项目中,我们必须采取预防措施来克服这个问题,方法是制定不同的时间表(产生了另一个问题,但在我们的控制范围内)

【讨论】:

以上是关于Hibernate/MySQL 批量插入问题的主要内容,如果未能解决你的问题,请参考以下文章

MyCat批量插入

mysql存储过程怎样批量插入数据

哪种方法最适合批量插入?

c#中往mysql里批量插入上万条数据,有比较高效的方法吗

SQL中用循环批量插入数据如何实现

在EXCEL的表格中如何批量插入不同内容的批注