2

すべてのテーブルの主キーが単純な int 列として宣言されている中程度のサイズの SQL Server 2008 データベース (約 120 個のテーブル、バックアップは約 4GB 圧縮) を使用しています。

現在、主キー値は NHibernate によってインクリメントID ジェネレーターによって生成されます。これはこれまでのところうまく機能していますが、マルチプロセッシング環境への移行は妨げられています。

システムの負荷が増大しているため、共通のデータベース バックエンドにアクセスする複数のサーバーを使用できるようにするために必要な作業を評価しています。

hi-loジェネレーターへの移行が最善の方法のようですが、そのような移行がどのように機能するかについての詳細はわかりません。

NHibernate は自動的に hi-lo テーブルに行を作成しますか、それとも手動でスクリプトを作成する必要がありますか?

NHibernate が行を自動的に挿入する場合、既存のキー値を適切に考慮しますか?

NHibernate が自動的に処理してくれるなら、それはすばらしいことです。そうでない場合、役立つツールはありますか?

アップデート

NHibernate のインクリメント識別子ジェネレーターは、完全にメモリ内で動作します。テーブルから使用される識別子の最大値を選択することによってシードされますが、その時点から、基になるデータベース テーブルを参照せずに、単純なインクリメントによって新しい値を割り当てます。他のプロセスがテーブルに行を追加すると、主キーの競合が発生します。1 つのプロセス内で複数のスレッドを実行することはできますが、複数のプロセスを実行することはできません。

比較のために、NHibernate IDジェネレーターは、ID 列を使用してデータベース テーブルを構成し、主キーの生成をデータベースに制御させることによって機能します。これはうまく機能しますが、作業単位パターンが損なわれます。

hi-loアルゴリズムはこれらの間に位置します。主キーの生成はデータベースを通じて調整され、マルチプロセッシングが可能になりますが、実際の割り当ては完全にメモリ内で行われ、作業単位パターンの問題を回避できます。

4

3 に答える 3

2

hi-lo ジェネレーターを使用するには、生成されたキーの "Hi" 部分の次の値を格納するルックアップ テーブルを作成する必要があります。エンティティ テーブルごとに個別の列を作成するか、すべてのエンティティで使用される単一の列を作成するか、2 つのオプションを組み合わせて作成するかを選択できます。

共有列が使用されている場合、生成された各キーは単一のエンティティによってのみ使用されます。これは、多数のエンティティ テーブルがある場合に適していますが、生成できる Id の総数が減少します。

たとえば、このプロジェクトではHiLoLookup3 つの列を持つテーブルを使用します。

NextEntityId BIGINT NOT NULL,
NextAuthenticationLogId BIGINT NOT NULL,
NextConfigurationLogId BIGINT NOT NULL

ログ テーブルには大量の挿入があるため、Hi 値の別のプールが与えられています。通常のエンティティ テーブルの主キー列は 64 ビットBIGINTデータ型を使用するため、ID のシーケンスに大きなギャップがあってもオーバーフローする危険はありません。管理オーバーヘッドを削減するために、ID の共有プールが使用されます。

hi-lo ジェネレーターには、既存のキーと競合しない開始値で自身を初期化する組み込みサポートがないため、手動で実行する必要があります。開始の「hi」値として使用する値は、いくつかの考慮事項によって異なります。

  • 既存の ID の最大値 - 重複を避けるために、生成される ID はこれより大きくする必要があります
  • データベースから新しい「hi」値を要求する前に生成する必要がある ID の数 ( max_lo) - 値を大きくすると同時実行性が向上しますが、特にサービスが頻繁に再起動される場合は ID が無駄になる可能性が高くなります

エンティティ マッピングで提供されるmax_lo値は、最初の「hi」値を決定する際に重要です。たとえば、既存の ID の最大値が 12345 のテーブルがあるとします。データベースに戻る前に生成する必要がある ID の数は 1000 です。この場合、最初の hi 値は である必要が(12345 / 1000) + 1 = 13あり、最初に生成される ID は 13000 になります。 . HiLoGenerator 実装の癖により、エンティティ構成で提供される値は1000ではなくmax_lo999 である必要があります

.hbmマッピングを使用する場合:

<generator class="hilo">
    <param name="table">dbo.HiLoLookup</param>
    <param name="column">NextEntityId</param>
    <param name="max_lo">999</param>
</generator>
于 2012-05-31T05:31:10.807 に答える
1

従来のHiLoとは別に、新しい拡張IDジェネレーターを調べることもできます。これらは、HiLoの動作と精神的に類似したテーブル(またはデータベースがサポートしている場合はシーケンス)を使用できますが、(必要に応じて)異なるエンティティの個別の番号シリーズのサポートが構築されています。拡張IDジェネレーターを使用すると、HiLoアルゴリズムまたはプールされたアルゴリズムのいずれかを使用するオプションもあります。「プール」の利点は、idジェネレーターテーブルがその一部だけでなく実際の値を表示することです。

これらはNHibernate3.3の新機能です。リファレンスドキュメントにはまだそれらが記載されていませんが、Hibernateドキュメントには記載されています。それらはNHibernateでも同じように機能します。

于 2012-06-01T11:21:44.753 に答える
0

UOW を壊さず、複数の挿入ステートメントをサーバーに送信できるため、HILO を使用することを好みます。

今あなたの質問のために: -

NHibernate は自動的に hi-lo テーブルに行を作成しますか、それとも手動でスクリプトを作成する必要がありますか?

hilo テーブルを作成する必要があります。hilo には 2 つの種類があります。すべてのテーブルに 1 つの数字を使用するか、いずれかのテーブルに 1 つの数字を使用します。私は後者の方が好きです。

NHibernate が行を自動的に挿入する場合、既存のキー値を適切に考慮しますか?

maxhi/maxlo を手動で設定する必要があります。lo はマッピングにあり、hi はテーブルにあるため、XML マッピングを次のように変更する必要があります。

<id name="Id" column="Id" unsaved-value="0">
    <generator class="hilo">
        <param name="column">NextHi</param>
        <param name="where">TableName='CmsLogin'</param>
        <param name="max_lo">100</param>
    </generator>
</id>

次に、次の SQL を (手動で) 生成できます。

CREATE TABLE hibernate_unique_key (
  TableName varchar(25) NOT NULL,
  NextHi bigint NOT NULL
)

次に、hilo を使用するすべてのテーブルのデータベースに行を追加します。

CmsLogin,123
Address, 456

ここの 123 は、次の挿入 ID を (123 x 100) = 12300 に開始することに注意してください。したがって、12300 が現在の ID よりも大きい限り、すべて問題ありません。

デフォルトのテーブル名が気に入らない場合は、hibernate_unique_keyこれをミックスに入れることができます

<param name="table">HiloValues</param>
于 2012-05-31T04:30:24.913 に答える