web-dev-qa-db-ja.com

増分-1のIDENTITY列を使用する

同時に両方に書き込む2つの別々のデータセンターにある2つのメインテーブルでSQLサーバーログデータベースを実行する必要があります。

私はデータベースを新しいデータセンターに復元し、ID列を-1に再シードし、増分を-1に設定するというアイデアを持っていました。これにより、データを組み合わせる必要があるときにIDが重複する可能性がなくなります。 DATACENTRE1は正の整数、DATACENTRE2は負の整数になります

-1の増加は問題を引き起こしますか?

4
DamagedGoods

後退するのは私には間違っていると感じています。

2つのデータセンターだけで、ID範囲を実装することもできます。驚異的な速さでID値を循環しない限り、次のことができない理由はありません。

-- Data center 1
CREATE TABLE dbo.Table
(
  ID INT IDENTITY(1,1) PRIMARY KEY
  -- , ...
);

-- Data center 2
CREATE TABLE dbo.Table
(
  ID INT IDENTITY(1000000000,1) PRIMARY KEY
  -- , ...
);

これにより、データセンター2との衝突で危険が生じる前に、データセンター1で10億(まあ、999,999,999)の値を生成できます。また、優先順位に応じて、データセンター1にCHECK制約を追加して、値の重複を防ぐことができます。エラーと重複。アプリの存続期間中にいずれかのデータセンターで実際に10億を超える値が生成されることが懸念される場合は、他のデータセンターの下限にどれだけ近いかを定期的にチェックする繰り返しジョブを実装することもできます(気にしないでください)あなたのもの)。

約10億個では不十分な場合は、呼吸する余地を増やすための2つの代替策があります。

-- Data center 1
  ID INT IDENTITY(-2147483648,1)

-- Data center 2
  ID INT IDENTITY(1,1)

これにより、各データセンターに20億を超える重複しない値が与えられ、データセンター1が0に近づくまで衝突の危険はありません。それでも十分でない場合:

-- Data center 1
  ID BIGINT IDENTITY(-9223372036854775808,1)

-- Data center 2
  ID BIGINT IDENTITY(1,1)

または、すべての値を0よりも大きくしたい場合は、正の範囲をおよそ半分に分割することができます(私より知識が豊富な場合は、これよりも少し正確にすることができます)。

-- Data center 1
  ID BIGINT IDENTITY(1,1)

-- Data center 2
  ID BIGINT IDENTITY(4611600000000000000,1)

その数の言い方すらわかりませんが、それは途方もない数です。そして実際には、あなたが偉大な偉大な偉大な偉大な孫が大学を卒業するまでに、これらのすべての価値を使い果たすには、非常に高速なコンピューターで非常に一生懸命働かなければならないでしょう。また、Enterprise Editionを使用している場合は、データ圧縮を使用して、少なくともデータセンター1で20バイトを超えるまで、8バイトすべてにヒットを支払う必要がないようにすることができます。


私が管理したシステムでは、これを少し異なる方法で行いました。企業内で一意である必要があるID番号の生成を担当するExpressインスタンスを備えた複数のWebサーバーがありました。そのため、BIGINT IDENTITY列を使用して、各マシンにシーケンスジェネレーターをセットアップしました(実際に値を格納する必要はありませんでした)。 9台未満のサーバーがあったため、これらはすべて次のようにシードされました。

-- WEBAPP0001
ID BIGINT IDENTITY(10000000000,1)

-- WEBAPP0002
ID BIGINT IDENTITY(20000000000,1)

-- WEBAPP0003
ID BIGINT IDENTITY(30000000000,1)

...

値が使用され、中央システムにマージされたとき、重複がないことが保証されただけでなく、コンポジットを導入することなく、それらがどのWebサーバーからのものかを即座に認識することも簡単でした(これはデバッグに役立つ場合もありました)。重要な要件。また、1つのWebサーバーが100億を超える値を生成するという懸念はありませんでした。

このシナリオでは、多くの人がGUIDを使用しますが、そのアプローチにはいくつかの強力な議論があると思います。

9
Aaron Bertrand

SQL Serverで問題が発生することはありません。


create table decrement(
id integer identity(0,-1),
test int
)

insert into decrement (test) select number from numbers

select top 10 id, test from decrement order by id asc
go
id  test
------------
-5103   5110
-5102   5109
-5101   5108
-5100   5107
-5099   5106
-5098   5105
-5097   5104
-5096   5103
-5095   5102
-5094   5101

しかし、長期的には良い考えは別の問題かもしれません。他の人は混乱してしまうかもしれません(つまり、上記のクエリの順序は逆になっているため、通常とは逆に考える必要がありました)。または、他の誰かがデータベースを復元し、IDENTITYを「通常」の方法で再シードして、IDが重複した場合はどうなりますか?

スキーマを変更して「サイト」列を作成することは可能ですか?次に、サイトとIDを複合キーとして使用しますか?

7
Stuart Moore

この設定で発生する可能性があるいくつかの問題:

@ Martin Smith's コメントのリンクをたどると、ID列の負の値が一部のアプリケーションで問題を引き起こす可能性があります。データベース設計者がIDENTITY列を最小値から開始しない理由1ではなく

別の問題は、値が負であるのに減少していること、およびIDがテーブルのクラスター化されたキーでもあるかどうかに関連しています。 Bツリー構造は、左から右に(低い値から高い値に)トラバースする場合、および挿入が右側(高い)側で行われる場合に効率的です。キーが増え続けるとき。このプロパティは、テーブルのクラスター化されたキーにとってより重要です。クラスタ化されたキーの最良のプロパティについて、特にever-increeasingであることについて、このブログ投稿Kimberly Trippを参照してください。

減少するキーを使用すると、常にインデックスの反対側(左側)にデータが挿入され、インデックスの断片化が発生します。影響はあなたのケースにとって重要ではないかもしれませんが、IDがクラスター化されたキーとしても選択されている場合は、これを念頭に置いておく必要があると思います。

または、@ Martinが示唆するように、(-1)データセンターのクラスタ化インデックスもDESCとして定義します。これにより、断片化に関する上記の問題が回避されます。


増加するIDを維持しながら同じ機能を実現する他のオプションは、1つのデータセンターで偶数の値を、もう1つのデータセンターで奇数(両方とも+2インクリメント)にするか、@ Stuartが示唆するようにsiteIDを主キーに追加することです。

7
ypercubeᵀᴹ

これは、キーによるデータ分割のバリエーションのように聞こえます。別の方法は、シードとインクリメントを使用して、各データセンターがインターリーブするが衝突しない値を生成することです。次のようなものを試してください:

DC #1: IDENTITY (1, 2)
DC #2: IDENTITY (2, 2)

各テーブルのID値にはギャップがあります。

DC #1 has values: 1, 3, 5, ...
DC #2 has values: 2, 4, 6, ...

今後DCを追加する可能性があると思われる場合は、増分をDCの数(たとえば4)に設定します。ロールインすると、次のようになります。

DC #1: IDENTITY ( 1, 4)
DC #2: IDENTITY ( 2, 4)
DC #3: IDENTITY ( 3, 4)
DC #4: IDENTITY ( 4, 4)
3
James Page

やってみなよ! (そして、ここに報告してください:-))。

いいえ、問題はありません-結局、INTのデータ範囲は-20億から+20億です-負の数が正のIDENTITYの数と異なる動作をする理由がわかりません...

3
marc_s

私が使用したアプローチは次のとおりです。

  • 各サーバーの順次値を開始し、予想されるサーバー数よりも大きい値で増分します。
  • サーバーごとに異なる範囲を使用します。
  • 両方のサーバーに共通のシーケンスを使用します。

各ソリューションには長所と短所があります。

1
BillThor