我想问一下有关CrudRepository中save()的性能。 首先是一个代码示例。
for(int i=0; i<5000; i++){
Example example = new Example(0, true, false, i, "example");
example = exampleRepository.save(example);
List<ChildExample> childExamples = new ArrayList<>();
ChildExample childExample = new ChildExample(0, i, true, example);
childExamples.add(childExample);
childExampleRepository.saveAll(childExamples);
}
这只是一个示例,但是一切都必须保持原样(例如创建示例列表,然后使用saveAll,级联等。这是不允许的。)
我观察到了什么?前2000个对象的保存速度非常快-假设:10分钟。但是-下一个2000年的保存时间更长,大约30分钟。这是为什么?为什么保存每个后续项需要更长的时间?如果我使用JpaRepository和saveAndFlush()怎么办?如果我使用saveAndFlush()会缩短此过程吗?
答案 0 :(得分:2)
当您击中save()
相当于entityManager.persist()
时,持久性提供程序不会在物理数据库上隐式执行INSERT
。它只是将给定实体存储在其持久性上下文中。已在当前会话缓存(一级缓存)中对其进行管理。
这是为了防止不必要的CRUD
操作重载。默认情况下,更改将在提交当前事务时刷新(或在达到特定情况的托管实体阈值(如您的情况)时)。在交易期间执行SELECT
操作时,如果其中包含JOINs
中某处的持久化实体,则也可能触发隐式刷新(虽然这里不是这种情况)。
使用flush
时,持久性提供程序此时必须在数据库上执行物理保存。
但是会提高性能吗?这个问题没有明确的答案,它完全取决于每种独特的情况。不过,这是一个选项,您需要执行一组测试才能找出答案。
您还可以摆弄hibernate.jdbc.batch_size
。如果您针对特定的情况正确配置此配置,则可能会收获很多。