Hi / Loアルゴリズムとは何ですか?
これはNHibernateのドキュメントで見つかりました(一意のキーを生成する1つの方法、セクション5.1.4.2です)が、それがどのように機能するかについての適切な説明は見つかりませんでした。
私はNhibernateがそれを処理することを知っており、内部を知る必要はありませんが、興味があるだけです。
Hi / Loアルゴリズムとは何ですか?
これはNHibernateのドキュメントで見つかりました(一意のキーを生成する1つの方法、セクション5.1.4.2です)が、それがどのように機能するかについての適切な説明は見つかりませんでした。
私はNhibernateがそれを処理することを知っており、内部を知る必要はありませんが、興味があるだけです。
回答:
基本的な考え方は、主キーを構成するために「高い」番号と「低い」番号の2つの番号があるということです。クライアントは基本的に「高」シーケンスをインクリメントできます。これにより、さまざまな「低」値を持つ以前の「高」値の範囲全体からキーを安全に生成できることがわかります。
たとえば、現在の値が35である「高い」シーケンスがあり、「低い」数が0〜1023の範囲にあるとします。次に、クライアントはシーケンスを36に増やし(他のクライアントが35を使用しているときにキーを生成できるようにするため)、キー35 / 0、35 / 1、35 / 2、35 / 3 ... 35/1023がすべて利用可能。
主キーなしで値を挿入してからクライアントにフェッチする代わりに、クライアント側で主キーを設定できると(特にORMで)非常に便利です。別に何か他のものから、それはあなたが簡単に親/子関係を作り、あなたが行う前に、すべての場所に鍵を持つことができることを意味任意の単純それらをバッチ処理になり挿入し、。
ジョンの答えに加えて:
切断された状態で作業できるようにするために使用されます。その後、クライアントはサーバーに高数値を要求し、低数値自体を増やすオブジェクトを作成できます。lo範囲が使い果たされるまで、サーバーに接続する必要はありません。
これは非常に一般的な質問であるため、この回答に基づいてこの記事を作成しました。
hi / loアルゴリズムは、シーケンスドメインを「hi」グループに分割します。「hi」の値は同期して割り当てられます。すべての「hi」グループには、最大数の「lo」エントリが与えられます。これは、同時に重複するエントリを心配することなくオフラインで割り当てることができます。
識別子の範囲は次の式で与えられます。
[(hi -1) * incrementSize) + 1, (hi * incrementSize) + 1)
「lo」の値は次の範囲になります。
[0, incrementSize)
次の開始値から適用されます:
[(hi -1) * incrementSize) + 1)
すべての「lo」値が使用されると、新しい「hi」値がフェッチされ、サイクルが継続します
あなたはこの記事でより詳細な説明を見つけることができます:
また、この視覚的なプレゼンテーションも簡単に理解できます。
hi / loオプティマイザーは識別子の生成を最適化するのに適していますが、データベースに行を挿入する他のシステムではうまく機能せず、識別子の戦略について何も知りません。
Hibernateはプールされたloオプティマイザーを提供します。これはhi / loジェネレーター戦略の利点を提供すると同時に、このシーケンス割り当て戦略を認識していない他のサードパーティクライアントとの相互運用性を提供します。
他のシステムと効率的で相互運用可能なため、pooled-loオプティマイザーは、従来のhi / lo識別子戦略よりもはるかに優れた候補です。
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "name") @SequenceGenerator(name="name", sequenceName = "name_seq", allocationSize=100)
IDに使用しています。
, (hi * incrementSize) + 1)
...であるはず, hi * incrementSize)
ですよね?
Loはキャッシュされたアロケーターで、キースペースを大きなチャンクに分割します。通常、人間が賢明に選択できる意味のあるサイズの範囲(一度に200キーを取得するなど)ではなく、いくつかのマシンワードサイズに基づいています。
Hi-Loを使用すると、サーバーの再起動時に多数のキーが浪費され、人間にとって不便な大きなキー値が生成される傾向があります。
Hi-Loアロケーターよりも優れているのは、「線形チャンク」アロケーターです。これは、同様のテーブルベースの原則を使用しますが、小さくて便利なサイズのチャンクを割り当て、人間が使いやすい値を生成します。
create table KEY_ALLOC (
SEQ varchar(32) not null,
NEXT bigint not null,
primary key (SEQ)
);
次を割り当てるには、たとえば、200個のキー(サーバーで範囲として保持され、必要に応じて使用されます):
select NEXT from KEY_ALLOC where SEQ=?;
update KEY_ALLOC set NEXT=(old value+200) where SEQ=? and NEXT=(old value);
このトランザクションをコミットできる場合(再試行を使用して競合を処理する)、200個のキーを割り当て、必要に応じてそれらを分配できます。
チャンクサイズがわずか20のこのスキームは、Oracleシーケンスから割り当てるよりも10倍高速で、すべてのデータベース間で100%移植可能です。アロケーション性能はハイローと同等です。
アンブラーのアイデアとは異なり、キースペースは連続した線形のナンバーラインとして扱われます。
これにより、複合キーの推進力(実際には決して良い考えではありませんでした)が回避され、サーバーの再起動時に単語全体が無駄になることが回避されます。「友好的な」人間規模のキー値を生成します。
対照的に、アンブラー氏のアイデアは、上位の16ビットまたは32ビットを割り当て、hi-wordsが増加するにつれて、人間に不便な大きなキー値を生成します。
割り当てられたキーの比較:
Linear_Chunk Hi_Lo
100 65536
101 65537
102 65538
.. server restart
120 131072
121 131073
122 131073
.. server restart
140 196608
設計的には、彼のソリューションは、Linear_Chunkよりも基本的に数直線(複合キー、大きなhi_word製品)で複雑ですが、比較上の利点はありません。
Hi-Lo設計は、OOマッピングと永続化の初期に発生しました。最近のHibernateなどの永続化フレームワークは、デフォルトとしてよりシンプルで優れたアロケータを提供しています。
Hi / Loアルゴリズムは、私の経験に基づく複製シナリオを持つ複数のデータベースに最適であることがわかりました。これを想像してみてください。ニューヨーク(エイリアス01)にサーバーがあり、ロサンゼルス(エイリアス02)に別のサーバーがある場合、PERSONテーブルがあります...したがって、ニューヨークでは、ユーザーが作成されると、HI値として常に01を使用します。そしてLO値は次の秘密です。例。
ロサンゼルスでは、常にHI 02を使用します。次に例を示します。
したがって、データベースレプリケーションを使用すると(どのブランドでも)、主キーの重複や衝突などを心配することなく、すべての主キーとデータが簡単かつ自然に結合されます。
これは、このシナリオでの最善の方法です。