GUID対INT-主キーとしてどちらが良いですか?


97

私は使用する理由としない理由について読んGuidでいintます。

int小さく、速く、覚えやすく、時系列を保持します。そして、Guid私が見つけた唯一の利点は、それがユニークであることです。どちらの場合、a Guidはa よりも優れており、intその理由は?

私が見たものからint、多くの場合、無関係である数の制限を除いて、欠陥はありません。

なぜ正確にGuid作成されたのですか?実際には、単純なテーブルの主キーとして機能する以外の目的があると思います。(Guid何かに使用する実際のアプリケーションの例は?)

(Guid = UniqueIdentifier)SQL Serverのタイプ


1
のではなく、主キー、私はあなたの意味だと思う代理自然キーではないキーすなわちキーを(後者は、我々は現実の世界で使用キー)。おそらくクラスター化インデックスを意味します。
12

(プライマリ)KEYとINDEXの違いも覚えておいてください。
アランS.ハンセン14年


2
int数の制限を除いて、欠陥はありません。多くの場合、これは無関係です。」:実際には、INT対GUIDのこのコンテキスト内で、符号付き32ビットのINT上限は、符号付きの上限を考慮すると完全に無関係です。 、64ビットBIGINTはほとんどすべての用途をはるかに超えており(下限で番号付けを開始する場合はさらに大きくなります。同じINTことがに当てはまります)、それでもGUIDの半分のサイズ(16ではなく8バイト)とシーケンシャルです。
ソロモンラッツキー

回答:


89

これは、スタックオーバーフローでここここで尋ねられまし

Jeffの投稿では、GUIDの使用の長所と短所について多くのことを説明しています。

GUIDの長所

  • すべてのテーブル、すべてのデータベース、すべてのサーバーで一意
  • 異なるデータベースのレコードを簡単にマージできます
  • 複数のサーバーにデータベースを簡単に分散できます
  • データベースに往復する代わりに、どこでもIDを生成できます
  • とにかく、ほとんどのレプリケーションシナリオにはGUID列が必要です

GUIDの短所

  • これは、従来の4バイトのインデックス値の4倍の大きさです。注意しないと、パフォーマンスとストレージに深刻な影響を与える可能性があります
  • 面倒なデバッグ(where userid='{BAE7DF4-DDF-3RG-5TY3E3RF456AS10}'
  • 生成されたGUIDは、最高のパフォーマンス(newsequentialid()SQL Server 2005+など)とクラスター化インデックスの使用を可能にするために、部分的にシーケンシャルである必要があります

パフォーマンスに確信があり、レコードの複製またはマージを計画していない場合は、を使用しintて自動インクリメント(SQL ServerのIDシード)を設定します


20
GUIDアプローチのもう1つの欠点は、エンドユーザーの識別子として使用できないことです。注文「BAE7DF4-DDF-3RG-5TY3E3RF456AS10」に問題があることをユーザーが電話で伝えることを本当に期待していますか?:)
ブラン

3
シーケンシャルGUIDを使用せず、主キーがクラスター化されている(SQL Serverのデフォルト)場合、すべてのデータ挿入はテーブル全体にランダムに分散され、データの大規模な断片化につながります。これは、データが通常時系列などの何らかの順序で挿入されることを前提としています。
datagod

6
シーケンシャルGUIDは、SQLインスタンスが再起動されるまでのみシーケンシャルです。その場合、ルート値の生成方法により、最初の値が以前のものよりも低くなる可能性が高くなり、あらゆる種類の問題が再び発生します。
mrdenny

20
@Brann理想的には、そもそもエンドユーザーにあなたのPK値が与えられないことが理想です。そうすることはいくぶん一般的であると知っていますが、それは私がそうしないことを学ぶ前に私自身が過去にやったことです。しかし、実行するべきではないため、GUIDよりもINTを優先する特定の理由は有効ではありません。
ソロモンラッツキー

2
@ChadKuehn 上限があるので選択UNIQUEIDENTIFIERするINTことINTは、無制限であることは十分に真実ではありますが、実際的な利点ではないため、推論がやや不十分です。INT1の代わりに下限(-21億4,000万)から開始することにより、anの有効容量を簡単に2倍にできます。または、43億全体では不十分な場合BIGINTは、まだ8バイトのGUIDの16と比較して、それはシーケンシャルです。
ソロモンラツキー

18

データを外部ソースと同期している場合、永続的なGUIDの方がはるかに優れています。GUIDを使用している簡単な例は、顧客に送信されてネットワークをクロールし、特定のクラスの自動検出を行い、見つかったレコードを保存し、すべての顧客レコードが中央データベースに統合されるツールです。私たちの終わりに戻ります。整数を使用すると、7,398個の「1」が得られます。どの「1」がどれであったかを追跡するのは非常に困難です。


3
GUIDは外部識別子として間違いなく優れており、その非クラスター化インデックスを「外部キー」として保持し、クラスター化インデックスと外部キーの関係の基礎となる「内部キー」としてintを保持します。何かがアーキテクチャの境界を越えようとしている場合(別のアプリとの通信など)、混同できないものがあることに感謝しています。
グレッグ

15

ハイブリッドアプローチを使用して成功しました。テーブルには、自動インクリメントの主キー整数id列と列の両方が含まれguidます。はguid、必要に応じて行をグローバルに一意に識別するためidに使用でき、行のクエリ、ソート、および人間の識別に使用できます。


3
id人間が行を識別するのにすでに十分な場合、GUIDはどのような値を与えますか?
マーティンスミス

6
idは、このテーブルの行を識別します。GUID(少なくとも理論上)は、既知のユニバースの任意の場所でこの行を識別します。私のプロジェクトでは、AndroidモバイルはそれぞれローカルのSQLiteデータベースに構造的に同一のテーブルのコピーを持っています。行とそのGUIDはそれぞれAndroidで生成されます。次に、Androidがバックエンドデータベースに同期されると、他のAndroidモバイルから作成された行と競合することを恐れることなく、そのローカル行がバックエンドテーブルに書き込まれます。
rmir​​abelle

2
@MartinSmith私は自分でこのアプローチを使用しましたが、非常にうまく機能します。GUIDは、NonClusteredインデックスを持つ単なる代替キーであり、アプリケーションから渡されますが、プライマリテーブルにのみ存在します。すべての関連テーブルはINTPK を介して関連付けられます。このアプローチが両方の世界で最高のものであることを考えると、このアプローチがあまり一般的でないことは奇妙に感じます。ほとんどの人は、アプリがグローバルな一意性や移植性のためにGUIDを使用するためにPKがGUIDである必要がないことに気付かないで、非常に絶対的な用語で問題を解決することを好むようです。
ソロモンラッツキー

1
@rmirabelleこのアプローチを考えていて、ためらっていましたが、あなたの答えは私を納得させました。基本的に、ワークアイテムの一意の識別子(どこからでもネットワーク経由で取得できる)が必要な状況にありますが、最初にデータベースに往復したくありません。GUIDはこれに適したソリューションですが、シーケンシャルクラスタ化キーを持たない場合、JOINははるかに遅くなると思います。
easuter

1
@easuter PKが関連する2つのFKの複合である必要がある多対多の「ブリッジ」テーブルなどで、「それだけのために」IDフィールドを追加しないことに同意します。しかし、ここでは、IDフィールドは単にそのためのものではないため、トレードオフではありません。システムを効率的に動作させることはかなり重要です;-)。そして、あなたの場合、GUIDは外部で生成されるので、それらが実際に一意であるとしても、一意であるとは保証されないと主張します。しかし、データの整合性に対する責任は、GUIDを代替キーにし、IDをPKにするのに十分な理由です:)
ソロモンラッツ

1

そこにあるいくつかのベストプラクティスでは、使用する値のセット全体をできるだけ少ないメモリで収容できるデータ型を使用する必要があることに言及しています。たとえば、小規模ビジネスで雇用主の数を格納するためにそれを使用していて、100に達する可能性が低い場合、int(smallintでさえ)がするのにbigint値を使用することを誰も提案しません。

もちろん、これの欠点は「拡張性に否定!」のようなものです。


また、これは完全に関連しているわけではありませんが、これには別の要因があります。過度ではない場合、私は通常、自動生成されていない主キーを使用することをお勧めします(意味がある場合)。たとえば、ドライバーの情報を保存している場合、「ID」の新しい自動生成列を作成するのではなく、ライセンス番号を使用するだけです。

これは本当に明白に聞こえるかもしれませんが、かなり忘れられていることがわかります。

コンテキストの場合:回答のこの部分は、PKをレコードの一意のデータ識別子にするデータ理論的アプローチから対処されました。ほとんどの場合、それらが既に存在するときにそれらを作成するため、前の答えです。

ただし、これらのデータポイントを厳密に制御できることは非常にまれであるため、修正や調整が必要になる場合があります。主キーではできません(できますが、苦痛になる場合があります)。

説明をありがとう@VahiD。


意味のある主キーを使用することはまったくお勧めできません。以下のシナリオを検討してください。誰かが間違ったライセンス番号を入力し、3〜4テーブルでこのIDを外部キーとして使用しました。この場合、単にライセンス番号を編集するだけでは十分ではありません。
VahiD

1
面白い:私はあなたのコメントを読んで、「はい、もちろん」と思ってから、答えに戻って「そう言った」と思ったのですか?数年で物事がどのように変化するか面白い。私はおそらくより理論的な背景から来ていましたが、それを厳密に制御しない限り(ほとんど)、それは多くの利点を提供しません。答えを更新します。
アルファ

年の開発への
賛成票

1

自動インクリメントIDを使用すると、ビジネスアクティビティに関する情報が漏洩する可能性があります。ショップを運営していてorder_id、購入を公に識別するために使用している場合、誰でも簡単な算術であなたの月間売上高を知ることができます。


0

GUIDの生成方法に関するもう1つのこと。mrdennyは、newsequentialid()が使用されている場合でも、インスタンスを再起動すると、新しい値が前の処理で残された「穴」から始まることを正しく指摘しました。「シーケンシャル」GUIDに影響するもう1つのことは、ネットワークカードです。記憶が正しければ、NICのUIDがGUIDアルゴリズムの一部として使用されます。NICを交換した場合、物事のシーケンシャルな側面を維持するためにUIDがより高い値になる保証はありません。また、複数のNICがアルゴリズムを使用した値の割り当てにどのように影響するかもわかりません。

ただ考えて、私は正しく覚えていると思います。すてきな一日を!


2
データベース管理者bobo8734へようこそ。これらのコメントのソースを見つけられますか?あなたがそれらに自信がないなら、多分彼らは(あなたがそれを担当しているとき)コメントとして提供される方がスタンドアロンの答えよりも良いでしょう。
LowlyDBA

-6

両方を使う

使用INT / BIGINT主キーのために、維持し、外部キー関係として使いやすいよう。

ただし、すべての行にも一意の列が含まれるように、列をGUIDにバインドします


2
この提案の背後にあるあなたの推論を説明することは誰も傷つけないだろう、と私は確信しています。
アンドリーM

GUIDは、長い間、あなたが特定のケースを探している場合を読み込むために困難になります36キャラクター..です
アブドゥル・阪南Ijaz

1
わかりましたが、回答で提案しているように、OPがintとの両方を使用する理由を実際には説明していませんguid。それに、あなたの提案を私だけに説明するのではなく、答え更新したいと思うかもしれません。ところで、別の回答者が既にあなたと同じ(多かれ少なかれ)を提案していることを知っていますか?
アンドリーM

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