在Java批处理中更新数百万行的最佳方法
我在遗留项目中使用justemain方法开发了一个批处理:使用mysql数据库的java7、hibernate和Spring 在这个批处理中,我想更新表中超过5000万行的几行。 当我每天开始批处理时,我必须更新至少10000行 那么,在mysql中更新行而不锁定表的最佳方法是什么 只需执行如下查询:在Java批处理中更新数百万行的最佳方法,java,mysql,spring,hibernate,Java,Mysql,Spring,Hibernate,我在遗留项目中使用justemain方法开发了一个批处理:使用mysql数据库的java7、hibernate和Spring 在这个批处理中,我想更新表中超过5000万行的几行。 当我每天开始批处理时,我必须更新至少10000行 那么,在mysql中更新行而不锁定表的最佳方法是什么 只需执行如下查询: update table items set is_achive = true where id in (id1,id2,id3....id10000) for(item p : ItemsLi
update table items set is_achive = true where id in (id1,id2,id3....id10000)
for(item p : ItemsList){
update table item set is_achive = true where id = p.id
}
或者使用如下的for循环:
update table items set is_achive = true where id in (id1,id2,id3....id10000)
for(item p : ItemsList){
update table item set is_achive = true where id = p.id
}
使用Hibernate标准生成器:
CriteriaBuilder cb = this.em.getCriteriaBuilder();
// create update
CriteriaUpdate<Order> update = cb.createCriteriaUpdate(Order.class);
// set the root class
Root e = update.from(Order.class);
// set update and where clause
update.set("amount", newAmount);
update.where(cb.greaterThanOrEqualTo(e.get("amount"), oldAmount));
// perform update
this.em.createQuery(update).executeUpdate();
CriteriaBuilder cb=this.em.getCriteriaBuilder();
//创建更新
CriteriaUpdate=cb.createCriteriaUpdate(Order.class);
//设置根类
Root e=update.from(Order.class);
//set update和where子句
update.set(“金额”,newAmount);
更新。其中(cb.greaterThanOrEqualTo(e.get(“金额”),oldAmount));
//执行更新
this.em.createQuery(update.executeUpdate();
这取决于您如何确定需要更新的行列表。如果查询数据库以确定列表,最好只使用DML语句,如:
UPDATE Item i SET i.achive = true WHERE ...
如果您关心的是锁定,即锁定行的时间量,则可以通过使用游标(例如数据源的某个id)来使用批处理
SELECT id FROM ... WHERE id >= :start AND ...
ORDER BY id
OFFSET 100 -- use a batch size that suites your needs
LIMIT 1 -- use a batch size that suites your needs
可以使用查询来实现更新的限制和限制
Integer end = entityManager.createQuery("SELECT id FROM ... WHERE id >= :start AND ... ORDER BY id")
.setParameter("start", previousEnd)
.setFirstResult(100) // batch size
.setMaxResults(1)
.getResultList().stream().findFirst().orElse(null);
然后执行这样的查询
UPDATE Item i SET i.achive = true WHERE i.id BETWEEN :start AND :end
或者如果结束为空,即最后一批使用
UPDATE Item i SET i.achive = true WHERE i.id >= :start
<> P>最好是尝试去根,如果它像克里斯B建议,但如果它是你不能做的事情,那么你也可以考虑利用Spring JDBC批量更新操作,如这里所记录的。这些文档已经存在了一段时间,所以请查找适合您所使用版本的文档
Hibernate将为您批量更新,但您可能会遇到其他问题(例如内存使用),最好先尝试更容易编写的方法,并在发现问题时解决问题如果更新必须是原子的,不要忘记启动事务。否则,如果运行过程中出现异常或错误,最终可能会出现部分更新。