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 批量插入问题的主要内容,如果未能解决你的问题,请参考以下文章