我有一个简单的用例,但它确实没有优化,我想知道它是否可以。
假设我有一个包含ID
的简单实体和一个名为price
的变量(该实体称为Product
)。
我正在使用Hibernate
和JPA
,我每小时都想更新我的产品价格,所以这里是伪代码:
List<Product> products = Product.retrieveAll();
for (Product p : products) {
p.price = makeSomeComplexComputationsToGetNextPrice();
p.save(); // Updates the entity in the DB
}
这段代码非常简单。 makeSomeComplexComputationsToGetNextPrice();
使用CPU进行一些计算,而且速度很快。
当我有100个产品时,一切正常(代码发出101个sql请求),但是假设我有10 000个产品,代码发出10 001个sql请求,这需要几秒钟。
这个用例是我的实际用例的简化版本,但问题在于:当我的产品太多时,执行需要太多时间(因为查询量很大)。
使用hibernate
和JPA
,是否有办法优化此类用例? (此代码执行时间不到一秒,并且由于所有查询而占用的时间超过1秒)
非常感谢你的帮助
答案 0 :(得分:2)
使用批次怎么样?我认为这通常就是这样做的。
http://docs.jboss.org/hibernate/orm/3.3/reference/en-US/html/batch.html
答案 1 :(得分:2)
最简单的优化方法是使用批量转移。尝试计算大小为N的大部分,然后同时存储整个N个产品。而不是为每个存储(开放连接,存储,刷新,关闭连接)做出努力,你只需每次批量。
当你选择整个产品作为bulksize时,更加容易,有效地使它成为一个load-computeeach-store算法。
否则选择完美的体积大小可能会很棘手,因为它取决于很多参数,例如对象大小,数据库及其参数硬件等等,但通常只需通过尝试不同的值来发现一个好的值测量时间。
其他方式可能包括并行性(因为您的IO是瓶颈似乎不合适)或调整数据库。
答案 2 :(得分:1)
正如@EricStein和@LastFreeNickname所指出的,使用批量插入,如果我们在p.save();
讨论INSERT命令,它就是一个解决方案。
但如果makeSomeComplexComputationsToGetNextPrice();
正在对某些SELECT请求进行数据库调用,那么首先查询这些复杂计算所需的所有数据,然后对其进行操作(再次使用批处理技术)插入)。