1. 概要

このクイックチュートリアルでは、SpringDataのsave()メソッドと saveAll()メソッドのパフォーマンスの違いについて学習します。

2. 応用

パフォーマンスをテストするには、エンティティとリポジトリを備えたSpringアプリケーションが必要です。

本のエンティティを作成しましょう:

@Entity
public class Book {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    private String title;
    private String author;

    // constructors, standard getters and setters
}

さらに、そのためのリポジトリを作成しましょう。

public interface BookRepository extends JpaRepository<Book, Long> {
}

3. パフォーマンス

パフォーマンスをテストするために、両方の方法を使用して10,000冊の本を保存します。

まず、 save()メソッドを使用します。

for(int i = 0; i < bookCount; i++) {
    bookRepository.save(new Book("Book " + i, "Author " + i));
}

次に、本のリストを作成し、 saveAll()メソッドを使用してすべての本を一度に保存します。

List<Book> bookList = new ArrayList<>();
for (int i = 0; i < bookCount; i++) {
    bookList.add(new Book("Book " + i, "Author " + i));
}

bookRepository.saveAll(bookList);

私たちのテストでは、最初の方法は約2秒かかり、2番目の方法は約0.3秒かかることに気づきました。

さらに、JPAバッチ挿入を有効にすると、 save()メソッドのパフォーマンスが最大10 % i n低下し、で最大60% on増加することが観察されました。 ] saveAll()メソッド。

4. 違い

2つのメソッドの実装を調べると、 saveAll()が各要素を反復処理し、各反復で save()メソッドを使用していることがわかります。 これは、パフォーマンスにそれほど大きな違いがあってはならないことを意味します。

さらに詳しく見ると、両方のメソッドに@Transactionalという注釈が付けられていることがわかります。

さらに、デフォルトのトランザクション伝播タイプは REQUIRED、です。これは、が指定されていない場合、メソッドが呼び出されるたびに新しいトランザクションが作成されることを意味します

この場合、 save()メソッドを呼び出すたびに新しいトランザクションが作成されますが、 saveAll()を呼び出すと、1つのトランザクションのみが作成され、後で再利用されます。 by save()

このオーバーヘッドは、以前に気付いたパフォーマンスの違いに変換されます。

最後に、バッチ処理が有効になっていると、トランザクションレベルで実行されるため、オーバーヘッドが大きくなります。

5. 結論

この記事では、SpringDataのsave()メソッドと saveAll()メソッドのパフォーマンスの違いについて学習しました。

最終的に、ある方法を別の方法よりも使用するかどうかを選択すると、アプリケーションのパフォーマンスに大きな影響を与える可能性があります。

いつものように、これらの例のコードはGitHubから入手できます。