save()性能-saveAndFlush()会更好吗?

时间:2019-08-03 17:12:13

标签: java spring jpa spring-data-jpa

我想问一下有关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()会缩短此过程吗?

1 个答案:

答案 0 :(得分:2)

当您击中save()相当于entityManager.persist()时,持久性提供程序不会在物理数据库上隐式执行INSERT。它只是将给定实体存储在其持久性上下文中。已在当前会话缓存(一级缓存)中对其进行管理。

这是为了防止不必要的CRUD操作重载。默认情况下,更改将在提交当前事务时刷新(或在达到特定情况的托管实体阈值(如您的情况)时)。在交易期间执行SELECT操作时,如果其中包含JOINs中某处的持久化实体,则也可能触发隐式刷新(虽然这里不是这种情况)。

使用flush时,持久性提供程序此时必须在数据库上执行物理保存。

但是会提高性能吗?这个问题没有明确的答案,它完全取决于每种独特的情况。不过,这是一个选项,您需要执行一组测试才能找出答案。

您还可以摆弄hibernate.jdbc.batch_size。如果您针对特定的情况正确配置此配置,则可能会收获很多。