「巨大な」データベーステーブルPKのシーケンシャルGUIDまたはbigint


14

この種の質問がたくさん出てくることは知っていますが、この決定を下すのに役立つ説得力のある議論をまだ読んでいません。我慢してください!

私には巨大なデータベースがあります-それは1日あたり約10,000,000レコード増加します。データはリレーショナルであり、パフォーマンス上の理由から、BULK COPYでテーブルをロードします。このため、行のキーを生成する必要があり、IDENTITY列に依存することはできません。

64ビット整数(bigint)は使用するのに十分な幅がありますが、一意性を保証するには、IDを作成するための集中ジェネレーターが必要です。私は現在、サービスがXシーケンス番号を予約し、衝突がないことを保証するようなジェネレーターサービスを持っています。ただし、この結果は、私が持っているすべてのサービスがこの1つの集中ジェネレーターに依存しているため、システムの配布方法が制限され、他の依存関係(ネットワークアクセスの要求など)に満足できませんこの設計によって。これはときどき問題になりました。

プライマリGUID(SQLの外部で生成される)としてシーケンシャルGUIDを使用することを検討しています。私自身のテストで確認できた限り、これらの唯一の欠点は、より広いデータ型のディスク領域のオーバーヘッドです(インデックスでの使用により悪化します)。bigintの選択肢と比較して、クエリのパフォーマンスが目に見えるほど遅くなることはありません。BULK COPYを使用したテーブルのロードはわずかに遅くなりますが、それほどではありません。GUIDベースのインデックスは、シーケンシャルGUID実装のおかげで断片化されていません。

基本的に、私が知りたいことは、私が見落としているかもしれない他の考慮事項があるかどうかです。現時点では、私は飛躍してGUIDを使い始めたいと思っています。私は決してデータベースの専門家ではないので、どんなガイダンスでも大歓迎です。


2
「シーケンシャルGUID」をどのように生成しますか?

それはカスタム実装です。これは基本的に、6バイトがタイムスタンプバイトで置き換えられたGUID型形式と、タイムスタンプが同じシーケンス番号を表す2バイトです。完全なシーケンシャル値を生成することは保証されていませんが、インデックスの断片化を私にとっては問題にしないのに十分です。

したがって、このデータを複数の異なるソースからロードしていますか?また、断片化について心配しているインデックスはクラスター化インデックスであると仮定していますか?

2
シーケンシャルGUIDを使用する場合は、NEWSEQUENTIALID()を確認する必要があります。必要なこと(単調増加)を実行する必要があり、カスタムコードに依存しません。

2
キーに関するトラブルについて Jeremiah Peschkaの投稿をご覧ください。よく読んでください。彼は何度もこれらの実装に対処しています。
billinkc

回答:


4

私も同じような状況です。現在、私はシーケンシャルGUIDアプローチを使用しており、断片化も簡単なキー生成もありません。

私は、bigintへの移行を開始した2つの欠点に気付きました。

  1. スペース使用量。インデックスごとに8バイト多くなります。それに10インデックス程度を掛けると、スペースの無駄が大きくなります。
  2. 列ストアインデックスはGUIDをサポートしていません。

(2)私にとってキラーだった。

次のようにキーを生成します。

yyMMddHH1234567890

私が使用していますリードする日付プラス時間をと持つシーケンシャル部分をその後。これにより、インデックスをまったく追加せずに、日付でデータを範囲クエリできます。これは私にとって素晴らしいボーナスです。

配布に適したHiLoアルゴリズムを使用して、bigintのシーケンシャル部分を生成します。

これがあなたの状況に移ることを願っています。bigintの使用をお勧めします。


1
これが最適であるため、これを「答え」としてマークします(そして、私が尋ねていることと、これが最初に表示されるほど簡単ではない理由を理解しているようです)。共有シーケンスジェネレーター(HiLoアルゴリズムの提案と同様に機能します)を使用すると思います。私はこれをいくつかの問題のない別のシステムで動作させていますが、余分な依存関係を我慢する必要があります。しかたがない。ありがとう。
バルガスト

3

INT1から始まるtypeを使用すると、20億行を超える可能性のある行を取得できます。これは、ほとんどの場合に十分なはずです。を使用するとBIGINT、約922兆円(15個のゼロを含む922-922'000 billion)を取得できますか?

あなたが使用している場合はINT IDENTITY、行を挿入し、毎秒1から始まる、とあなたを、あなたは66.5必要数年、あなたが20億限界を打つ前に....

あなたが使用している場合はBIGINT IDENTITY千行毎秒インサート1から始まり、そしてあなたを、あなたは気が遠くなる必要2.92億年あなたが922兆制限を打つ前に....

1日あたり1,000万行を使用すると、約1 '844'674'407'370日間(1844億日または50億年以上のティック)のデータに十分な数が必要になります-これで十分です?

詳細については、MSDN Books Onlineをご覧ください(すべてのオプションがあります)。


1
1日あたり1,000万行の挿入率は、200日でINT範囲を使い果たします。
mceda

@mceda:はい-私は何か他のものを主張しましたか?BIGINTただし、範囲をすぐに使い果たすことはありませんが... ...
marc_s

感謝しますが、質問で言ったように、データベースに送信する前にIDが必要です。データはリレーショナルなので、一括コピーする前に主キーと外部キーを割り当てる必要があります。それが目的でなければ、IDENTITY BIGINTはおそらく完璧でしょう。

2
@Barguast:ステージングテーブルにデータを(IDなしで)一括挿入し、そこから実際のデータテーブルに移動するにはBIGINT IDENTITYどうしますか?
marc_s

@marc_s:はい、提供される計算は「1から始まるINT IDENTITYを使用し、1秒ごとに行を挿入する場合、20億の制限に達するまでに66.5年が必要です」という質問と一致していません。
mceda

2

SQL 2012ではBIGINTデータ型のSEQUENCEを使用することをお勧めします。これはcache / nocacheなどのオプションを使用したIDENTITYよりもはるかに柔軟性が高く、バッチ操作のシーケンス範囲をsp_sequence_get_rangeとして割り当てることもできます。


残念ながら、SEQUENCEはSql Azureではサポートされていません。
ティモシーリーラッセル

2

ロードしている別々のテーブル間に外部キー関係がすでにあるため、IDENTITYを使用できない理由はありますか?そして、ステージング領域から生産領域への操作でそれらをリンクできる他の自然な鍵はありませんか?そのため、一括コピーする前に、ソースシステムで現在どのように「リンク」されているかについてもう少し知りたいのですが。複数のソースシステムが独自のシーケンスを使用するだけで、共有データベースに持ち込まれたときに競合するシーケンスが発生する可能性がありますか?

COMB ID /シーケンシャルGUID手法は私がよく知っている手法であり、データベースの外部で割り当てられたグローバルな一意性を効果的に必要とするときはいつでも実行可能です。これは、データベースの内外で使用可能な行IDです。そのため、高度に分散された環境または切断されたシナリオでは、それはOKの選択です

本当に必要ない場合を除き、余分な幅の違いは、データのサイズが大きくなり、これらのキーがすべてのインデックスと多くのクエリのワーキングセットにある場合に重要になるためです。

また、生成された分散では、行が実際にGUID列の順序になっていない場合、クラスター化インデックスキー(狭い、静的、増加する)でこれを使用する問題により、IDENTITYでのクラスタリングと比較して断片化が発生する可能性があります残ります。


0

一般にOUTPUTINSERTコマンドの句を使用して、両方のテーブルにデータを挿入し、IDフィールドに関連付けることができます。

タイムスタンプに基づく識別子は信頼できると見なされるべきではありません-それはハードウェアクロックから時刻同期サービスまで多くのことに依存するシステムクロックに依存します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.