弹簧数据保存与保存所有性能

我试图理解为什么 saveAll 比 Save Data 存储库中的 save 具有更好的性能。我正在使用,可以在这里看到。CrudRepository

为了进行测试,我创建并添加了10k个实体,这些实体只有一个id和一个随机字符串(对于基准测试,我将字符串保持为常量),添加到列表中。迭代我的列表并调用每个元素,花了40秒。调用相同的整个列表在2秒内完成。使用 30k 元素进行调用也花费了 4 秒钟。我确保在执行每个测试之前截断我的表。即使对 50 个子列表的调用进行批处理,也需要 10 秒和 30k。.save.saveAll.saveAll.saveAll

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

我试图浏览Spring Data源代码,但这是我发现的唯一有价值的东西。在这里,它似乎只是简单地迭代整个,并像我一样调用每个。那么,它是如何做到如此之快的呢?它是否在内部执行一些事务性批处理?.saveAllIterable.save


答案 1

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

请注意 的定义,它们都用 注释。如果项目配置正确(由于实体被保存到数据库中,情况似乎就是如此),这意味着每当调用这些方法之一时,都会创建一个事务。如果你在循环中调用,这意味着每次调用时都会创建一个新事务,但是在有一个调用的情况下,因此无论保存多少个实体,都会创建一个事务。savesaveAll@TransactionalsavesavesaveAll

我假设测试本身不是在事务中运行的,如果它在事务中运行,那么所有对 save 的调用都将在该事务中运行,因为默认事务传播是 ,这意味着如果已经打开了一个事务,则调用将在该事务中运行。如果您打算使用春季数据,我强烈建议您阅读有关春季交易管理的信息。Propagation.REQUIRED


答案 2

推荐