gpt4 book ai didi

java - 使用 JPA 提高 foreach 持久调用的性能

转载 作者:行者123 更新时间:2023-11-29 03:09:14 25 4
gpt4 key购买 nike

我们有这样的业务逻辑:

public class StuffLogic {
@Autowired
private Util util;
// ...

public void processStuffs() {
// Simply returns a list of 50k objects
List<Stuff> list = dao.getManyFilteredStuff();

for (Stuff act : list) {
act.setStatus(StatusEnum.SomeStatus);
}

util.mergeAll(list);
}
}

public class Util {
// ...

@Transactional
public void mergeAll(List<?> list) {
for (Object o : entities) {
entityManager.merge(o);
}
}
}

我们有很多实体(约 50 000 个)并希望提高性能(根据初步测量,我们目前每秒可以处理 1 000 个实体)。

你们对此有什么提示吗?

到目前为止我们尝试了什么:

  • 多线程。看起来如果我们使用多线程执行并进行处理,在不同的线程中持久化,它不会真正加快执行时间但会减慢大约 5 倍。我们在 Oracle 上,也许它使用表锁定代替更新的行锁定,因此所有线程都必须等待。
  • 不幸的是,使用单个批量更新不是一种选择,因为我们有许多听众引入了一些无法使用单个更新语句的魔法。

一些技术细节:我们使用 Oracle、JPA/Hibernate。

如有任何提示,我们将不胜感激!

最佳答案

您可以做几件事,当您一次更新所有内容时,一级缓存会越来越大。这可能会增加进行脏检查所需的时间。

所以在 x 条记录(找到最佳位置)之后,对 entityManager 进行刷新和清除。

public void mergeAll(List<?> list) {
int i = 0;
for (Object o : entities) {
entityManager.merge(o);
i++:
if (i ^ 50 == 0) {
entityManager.flush();
entityManger.clear();
}
}
}

现在您还可以指示 hibernate 批处理语句,为此您需要调整您的 hibernate 设置。首先是 hibernate.jdbc.batch_size 以启用批处理。

 hibernate.jdbc.batch_size=50 

这应该会减少向 oracle 发出的查询数量,而不是 50 个单个查询,它将是一个包含 50 个条目的查询。

如果您的修改同时导致更新和插入,您可能希望对它们进行排序,以便 hibernate 可以将它们组合在一起并使用批处理语句。

hibernate.order_inserts=true
hibernate.order_updates=true

如果您正在使用版本控制,您可能还需要将 hibernate.jdbc.batch_versioned_data 设置为 true

可以找到关于这些属性的好帖子 here .

关于java - 使用 JPA 提高 foreach 持久调用的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30346584/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com