web-dev-qa-db-ja.com

クラスターシーケンシャルGUID主キーと非クラスターGUIDおよびクラスターシーケンシャルIDの主キー

GUIDを主キーとして使用する場合、サイズとパフォーマンスに関して最適なソリューションは何かを理解しようとしています。 GUIDが必要な主な理由は、GUIDがマイクロサービスアーキテクチャに適しているためです。実際に何が一番かについては多くの議論があるようです。

主な2つの解決策は次のとおりです。

  1. 主キーは、クラスター化インデックスを使用した順次=​​GUID(真に順次ではないため、NEWSEQUENTIALID()で構築されたSQL Serverではなく、アプリケーションによって生成されます)として保持されます)。

  2. ランダムに生成された2つの主キー、ランダムに生成されたGUIDおよびクラスター化インデックスを使用した基本的なint IDENTITY列-アプローチは、このstackoverflow応答で最もよく説明されています here

どちらのソリューションが最適かわかりません。最初の方法は、私が読んだものから最も人気があり、広く使用されているようです。 2番目は、リンクされたstackoverflow応答からこの利点があるようです:

次に、考慮すべき別の問題があります。テーブルのクラスタリングキーは、テーブルのすべての非クラスタ化インデックスのすべてのエントリに追加されるため、できるだけ小さくする必要があります。

何かアドバイスをいただければ幸いです。

1
Callum Breen

GUID=キーを使用する場合は、NEWSEQENTIALID()でクラスター化インデックスを使用し、アプリケーションを続行します。代替の設計は、 実際のアプリケーションを注意深くテストすると、優れた代替設計が明らかになる可能性がありますが、単純なクラスター化インデックスを順次生成されるGUID。

GUIDがソート順の「中間」で生成され、挿入ポイントの変更が実際に問題にならない理由の詳細については、以下を参照してください。 Good Page Splits and Sequential GUIDキーの生成

INT(クラスター化)とUNQUEIDENTIFIER(非クラスター化)を使用すると、テーブルに非クラスター化インデックスが多数ある場合にスペースを大幅に節約できますが、この内部値が分散システムがローカルのみの値であるはずのものにグローバルな依存関係を誤って取得する可能性があるため、アプリケーションの他のレイヤーに漏れ、DBで作業している他の人がわかるように十分に文書化されていることを確認してください。

考慮すべき3番目のオプションがあります。クラスタリングキーになることから利益を得る可能性のある他のものがテーブルにありますか?おそらく、多くの範囲クエリが表示されるDATE列ですか?その列の範囲クエリではパフォーマンスが向上し、任意のUUIDと日付+一意名を使用した断片化の影響を受けませんが、8バイトの整数よりも大きい場合でも、UUIDに必要な16よりも小さくなります。精度に応じてDATETIMEまたは_DATETIME2_であっても、結果は12バイトであるため、システム管理の履歴テーブルを使用していて、これがベーステーブルである場合、sysStartTime

INT(またはそれ以下)であってもそれほど変化しない場合でも、それに加えて、一意化子はUUIDよりも小さいキーとなり、一意化子は事実上INT IDENTITY(1,1)になります。そのため、サイズ/パフォーマンス上の理由でのみ追加の列が存在するデータモデルを汚染する必要なく、追加のINT列のように動作します。

(NEWSEQUENTIALID()で構築されたSQL Serverではなく、アプリケーションによって生成されます。これは、実際にはシーケンシャルではないためです)

ただし、断片化の懸念を大幅に減らすのに十分な「連続性」があるので、それが唯一の問題である場合は、車輪の再発明の邪魔をしないでください。

1
David Spillett