19.5. コレクションのパフォーマンスの理解

前章ではコレクションとそのアプリケーションについて見てきました。本章では、実行時のコレクション関連の問題についてもう少し見ていきましょう。

19.5.1. 分類

Hibernate は3つの基本的なコレクションの種類を定義しています:
  • 値のコレクション
  • 一対多関連
  • 多対多関連
この分類はさまざまなテーブルや外部キー関連を区別しますが、私たちが知る必要のある関連モデルについてほとんどなにも教えてくれません。関連構造やパフォーマンスの特徴を完全に理解するには、 Hibernate がコレクションの行を更新、削除するために使う主キーの構造もまた考えなければなりません。これは以下の分類を提示します。
  • インデックス付きコレクション
  • set
  • bag
すべてのインデックス付きコレクション(マップ、リスト、配列)は <key><index> カラムからなる主キーを持っています。この場合、コレクションの更新は非常に効率的です。主キーは効率的にインデックス化され、Hibernate が特定の行を更新または削除しようとすると、その行を効率的に見つけることができます。
set は <key> からなる主キーと要素のカラムを持っています。これはコレクション要素のいくつかの型については効率的ではないかもしれません。特に複合要素、大きなテキスト、バイナリフィールドでは非効率です。データベースは複合主キーに効率的にインデックスを付けることができないからです。一方、一対多や多対多関連において、特に人工識別子の場合は同じぐらい効率的です。SchemaExport で実際に <set> の主キーを作りたいなら、すべてのカラムで not-null="true" を宣言しなければなりません。
<idbag> マッピングは代理キーを定義するため、更新は常に非常に効率的です。事実上、これは最善のケースです。
bag は最悪のケースです。 bag は要素の値の重複が可能で、インデックスカラムを持たないため、主キーは定義されないかもしれません。Hibernate には重複した行を区別する方法がありません。Hibernate はこの問題の解決のために、変更があったときには常に一回のDELETE による完全な削除を行い、コレクションの再作成を行います。これは非常に非効率的かもしれません。
一対多関連では、「主キー」はデータベースのテーブルの物理的な主キーではないかもしれないことに注意してください。しかしこの場合でさえ、上記の分類はまだ有用です。Hibernateがコレクションの個々の行をどのように「見つけるか」を表しています。