6

SQL Azure フェデレーションが IDENTITY プロパティまたは SEQUENCE をサポートしていないことを考えると、レコードを挿入するときに連番を生成する効率的な方法は何でしょうか?

たとえば、次の列を持つテーブルがあるとします。

CREATE TABLE [dbo].[Orders] (
    [TenantId] [uniqueidentifier] NOT NULL,
    [OrderId] [uniqueidentifier] NOT NULL,
    [OrderNumber] [int] NOT NULL
    CONSTRAINT [PK_Orders] PRIMARY KEY CLUSTERED (
        [TenantId] ASC,
        [OrderId] ASC
    )
) FEDERATED ON ([FederationKey] = [TenantId])

特定のテナントに挿入された注文ごとに、OrderId をインクリメントする必要があります。たとえば、テナント A の OrderId は 1、2、3... となり、テナント B の OrderId も 1、2、3... と独立したシーケンスになります。隙間がないのが理想です。

TenantId と OrderId は主キーのコンポーネントです。それらの値はアプリケーションによって設定され、シーケンスの生成の問題とは関係ありません。OrderId だけがビジネス上の意味を持つ連番を持ちます。また、TenantId はフェデレーションの配布キーです。

この MSDN ブログの記事では、オプション 1 で、シーケンスを保持するテーブルを用意し、分離されたトランザクションでストアド プロシージャを使用してシーケンスをインクリメントする方法について説明しています。各テナントは、シーケンスの最後に使用された値を保持するこのテーブルにレコードを持ちます。

スケーラビリティ、競合、リソースのロックを考慮すると、これが最適なアプローチでしょうか? SQL Azure フェデレーションの制限を考慮して、他に役立つトリックはありますか?

4

2 に答える 2

2

ここに2つの追加のアイデアがあります。

アプローチは、それがビジネスシナリオで可能である場合、これを非同期にするためにそのフィールドを更新する別のプロセスを持つことです。このアプローチでは、OrderNumberフィールドにNULL値を受け入れるようにする必要があります。どのOrderが最初に来たかを知り、正しいOrderNumberを取得するために、InsertedDateフィールドも追加します。冗長性のためにこの義務を実行する複数のワーカーロールがある場合、非同期処理はより複雑になります。その場合、各プロセスに作業中のレコードを割り当てる必要があります(したがって、OwnedByフィールドも必要です)。 UPDATEを使用して、各プロセスが独自のレコードで実行されていることを確認し、プロセスがクラッシュして孤立したままにならないようにした場合に、レコードの割り当てが期限切れになるようにします(したがって、AssignedOnフィールドも必要です)。ささいなことではありません...

そして、あなたは貧しい人のアプローチを持っています...星がちょうど十分に整列するとき、それはあなたが必要とするすべてであるかもしれません。楽観的同時実行アプローチを使用する場合は、挿入中に次の番号を使用してみて(特定のテナントIDとOrderIdに対して最初にMAX OrderNumberを選択)、次に挿入を実行します。挿入が失敗した場合(その目的でTenantId、OrderNumberに一意のインデックスを追加したため)、OrderNumberに1を追加するだけです。ここでの本当の問題は、再試行の頻度とこのアプローチが失敗する可能性です。比較的合理化されたビジネスプロセスがある場合、これは実際には失敗しない可能性があります。ただし、複数の方法から注文が絶えず追加されている場合、これは受け入れられないアプローチである可能性があります。

于 2012-03-12T02:42:38.413 に答える
2

あなたのシナリオに適合するためにどれだけの労力が必要になるかはわかりませんが、これも見て、微調整できるかどうかを確認してください: SnowMaker – Azure (またはその他のクラウド ホスティング環境) 用の一意の ID ジェネレーター

于 2012-03-12T06:34:24.860 に答える