1. 序章

このチュートリアルでは、Hi/Loアルゴリズムについて説明します。 これは主にデータベース識別子生成戦略として使用されます。

アルゴリズムの概要から始めましょう。 次に、Hibernateフレームワークに基づく実用的な例を示します。 最後に、アルゴリズムのユースケース、その利点、およびその欠点について説明します。

2. Hi/Loアルゴリズムの概要

2.1. 意味

Hi / Loアルゴリズムの主な目的は、データベース識別子として安全に使用できる数値の範囲を作成することです。 そのために、一般に high、low 、およびinitialSizeと呼ばれる3つの数値変数を使用します。

incrementSize 変数は、1つのバッチで生成できる識別子の最大数を保持します。 アルゴリズムの開始時に定義された定数値として扱う必要があります。 ランタイムを変更すると、複数のクライアントが同じHi/Lo構成を使用してエントリを永続化する環境で重大な問題が発生する可能性があります。

high 変数は通常、データベースシーケンスから割り当てられます。 その場合、誰も同じ番号を2回取得することはありません。

low 変数は、現在割り当てられている番号を[0 、incrementSize )の範囲で保持します。

これらの点が与えられると、Hi / Loアルゴリズムは[( hi – 1) * incrementalSize + 1 hi * incrementalSize[ X147X]))。

2.2. 擬似コード

Hi/Loアルゴリズムを使用して新しい値を生成する手順を見てみましょう。

  • lowincrementSize以上の場合は、 high に新しい値を割り当て、lowを0にリセットします。
  • 次の式を使用して新しい値を生成します:( high – 1)* initialSize + low
  • を1つインクリメントします
  • 生成された値を返します

3. 実例

Hi/Loアルゴリズムの動作を見てみましょう。 そのために、HibernateフレームワークとそのHi/Lo実装を使用します。

まず、使用するデータベースエンティティを定義しましょう。

@Entity
public class RestaurantOrder {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "hilo_sequence_generator")
    @GenericGenerator(
      name = "hilo_sequence_generator",
      strategy = "sequence",
      parameters = {
        @Parameter(name = "sequence_name", value = "hilo_seqeunce"),
        @Parameter(name = "initial_value", value = "1"),
        @Parameter(name = "increment_size", value = "3"),
        @Parameter(name = "optimizer", value = "hilo")
      }
    )
    private Long id;
}

これは、idフィールドが1つある単純なレストランの注文です。 HibernateでHi/Loアルゴリズムを正しく定義するには、 id フィールドの定義で、 sequence 戦略– hilo オプティマイザー–を選択し、 increment_sizeパラメーター。

Hi / Loアルゴリズムの動作を示すために、9つのレストランの注文をループで保持します。

public void persist() {
    Transaction transaction = session.beginTransaction();

    for (int i = 0; i < 9; i++) {
        session.persist(new RestaurantOrder());
        session.flush();
    }

    transaction.commit();
}

エンティティで指定された増分サイズに従って、次のhigh値のデータベースへの呼び出しは3回だけである必要があります。 データベースシーケンスが1から始まると仮定すると、生成された識別子の最初のバッチは[1,3]の範囲になります。

Hi / Loアルゴリズムが3を返し、Hibernateが次の識別子の値を要求すると、low変数の値はincrementSize定数に等しくなります。 その場合、新しいhigh値のデータベースへの次の呼び出しを行う必要があります。 新しいhigh値として2を使用すると、アルゴリズムは[4,6]の範囲の値を生成します。

最後に、次の high 値のデータベースへの最後の呼び出しが行われ、[7、9]の範囲の値がエンティティに割り当てられます。

persist()メソッドの実行中にキャプチャされたHibernateログは、これらの値を確認します。

Hibernate: call next value for hilo_seqeunce
org.hibernate.id.enhanced.SequenceStructure  - Sequence value obtained: 1
org.hibernate.event.internal.AbstractSaveEventListener  - Generated identifier: 1, using strategy: org.hibernate.id.enhanced.SequenceStyleGenerator
org.hibernate.event.internal.AbstractSaveEventListener  - Generated identifier: 2, using strategy: org.hibernate.id.enhanced.SequenceStyleGenerator
org.hibernate.event.internal.AbstractSaveEventListener  - Generated identifier: 3, using strategy: org.hibernate.id.enhanced.SequenceStyleGenerator
Hibernate: call next value for hilo_seqeunce
org.hibernate.id.enhanced.SequenceStructure  - Sequence value obtained: 2
org.hibernate.event.internal.AbstractSaveEventListener  - Generated identifier: 4, using strategy: org.hibernate.id.enhanced.SequenceStyleGenerator
org.hibernate.event.internal.AbstractSaveEventListener  - Generated identifier: 5, using strategy: org.hibernate.id.enhanced.SequenceStyleGenerator
org.hibernate.event.internal.AbstractSaveEventListener  - Generated identifier: 6, using strategy: org.hibernate.id.enhanced.SequenceStyleGenerator
Hibernate: call next value for hilo_seqeunce
org.hibernate.id.enhanced.SequenceStructure  - Sequence value obtained: 3
org.hibernate.event.internal.AbstractSaveEventListener  - Generated identifier: 7, using strategy: org.hibernate.id.enhanced.SequenceStyleGenerator
org.hibernate.event.internal.AbstractSaveEventListener  - Generated identifier: 8, using strategy: org.hibernate.id.enhanced.SequenceStyleGenerator
org.hibernate.event.internal.AbstractSaveEventListener  - Generated identifier: 9, using strategy: org.hibernate.id.enhanced.SequenceStyleGenerator

4. アルゴリズムの利点と欠点

Hi / Loアルゴリズムの主な利点は、次のシーケンス値に対するデータベース呼び出しの数の削減です。 initialSize の値を増やすと、データベースへのラウンドトリップの数が減ります。 明らかに、これはアプリケーションのパフォーマンスが向上することを意味します。 それに加えて、Hi / Loアルゴリズムは、インターネット接続が弱い環境で推奨される選択肢です

一方、Hi / Loアルゴリズムは、複数の異なるクライアントがデータベースの同じテーブルにデータを保持する環境では最適な選択ではありません。 サードパーティのアプリケーションは、識別子の生成に使用しているHi/Lo戦略を認識していない可能性があります。 その結果、現在アプリケーションで使用されている生成された数値範囲のエンティティIDを使用する可能性があります。 その場合、データを永続化するときに、修正が難しいエラーが発生する可能性があります。

5. 結論

このチュートリアルでは、Hi/Loアルゴリズムについて説明しました。

最初に、それがどのように機能するかを説明し、その擬似コードの実装について説明しました。 次に、Hibernateのアルゴリズム実装を使用した実際の例を示しました。 最後に、Hi/Loのメリットとデメリットをリストしました。

いつものように、この記事に示されているコードは、GitHubから入手できます。