Spring数据保存vs saveAll性能

Yot*_*yte 10 java spring hibernate spring-data spring-data-jpa

我试图理解为什么saveAll具有比Spring Data存储库中保存更好的性能.我使用的是CrudRepository从中可以看出这里.

为了测试我创建并添加了10k个实体,它们只有一个id和一个随机字符串(对于基准测试我保持字符串是一个常量)到列表中.迭代我的列表并调用.save每个元素,花了40秒..saveAll在2秒内完成相同的整个列表调用..saveAll用甚至30k元素调用花了4秒钟.我确保在执行每个测试之前截断我的表.即使将.saveAll电话拨打到50个子列表,也需要10秒才能获得30k.

.saveAll整个列表的简单似乎是最快的.

我试图浏览春数据源代码,但是是我发现的唯一有价值的东西.在这里,它似乎.saveAll只是迭代整个,Iterable.save像我一样调用每一个.那怎么快得多呢?它是在内部进行一些事务性批处理吗?

Yaz*_*ber 20

在没有你的代码的情况下,我不得不猜测,我认为这与为每个保存的对象创建新事务的开销有关,save而不是在开放一个事务的情况下saveAll.

注意的定义savesaveAll他们都与注解@Transactional.如果您的项目配置正确,这似乎是因为实体被保存到数据库,这意味着只要调用其中一个方法,就会创建一个事务.如果您正在调用save循环,这意味着每次调用时都会创建一个新事务save,但是在saveAll有一个调用的情况下,无论保存的实体数量是多少,都会创建一个事务.

我假设测试本身并不在事务中运行,如果要在事务中运行,那么所有对save的调用都将在该事务中运行,因为默认事务传播是Propagation.REQUIRED,这意味着如果有事务已打开调用将在其中运行.如果您计划使用spring数据,我强烈建议您阅读Spring中的事务管理.

  • 这并不完全准确。@Transactional默认传播级别是Required,这意味着在实际调用该方法之前应该存在事务。由于该传播级别,CrudRepository 不会自行创建事务。 (2认同)
  • @edward_wong 实际上谁创建了交易与他的问题无关,我并没有说是 CrudRepository 创建了交易。仍然提到默认传播很重要,因为与始终需要创建新事务的 Propagation.REQUIRE_NEW 不同,Propagation.REQUIRED 将继续使用在外部范围中创建的事务(以及与他的问题无关的其他语义),这解释了直接在自己的循环中调用 save() 或调用 saveAll() 之间的性能差异。 (2认同)