【发布时间】:2015-05-20 10:08:53
【问题描述】:
我们有一个类似这样的业务逻辑:
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);
}
}
}
我们有很多实体(约 50000 个)并希望提高性能(根据初步测量,我们目前每秒可以处理 1000 个实体)。
你们对此有什么提示吗?
到目前为止我们所做的尝试:
- 多线程。似乎如果我们使用多线程执行并进行处理,坚持在不同的线程中,它不会真正加快执行时间,但会减慢大约 5 倍。我们在 Oracle 上,也许它使用表锁定代替更新的行锁定,因此所有线程都必须等待。
- 很遗憾,使用单个批量更新不是一种选择,因为我们有许多听众在引入一些魔法,而这些魔法不适用于单个更新语句。
一些技术细节:我们正在使用 Oracle、JPA/Hibernate。
任何提示将不胜感激!
【问题讨论】:
-
我假设对
persist的调用在foreach循环内? -
是的,对不起,错字。基本上我们在某处有一个实用函数,它为每个元素调用persist(),并用@Transactional 标记。
-
请发布一些实际代码,因为目前我对交易一无所知,您使用单个循环还是多个循环涉及多少实体管理器。信息太少了……
-
我会假设循环也在一个事务中,并且实际上只有一个事务。拥有 5000 + 1 个事务并不是很快,因为启动/提交很慢。使用批处理而不是单个提交会加快速度,您也不应该使用
merge而不是persist(后者适用于新实体)。 -
根据要求,请使用未派生的实际代码,因为您现在无法使用(没有参数,方法名称不匹配)。
标签: java multithreading oracle hibernate jpa