主キーはどうですか?[閉まっている]


88

私のチームでのかなり活発な議論で、私はほとんどの人が主キーとして好きなものを考えるようにさせられました。次のグループがありました

  1. Int / BigIntは、自動インクリメントで十分な主キーです。
  2. 主キーを構成する列が少なくとも3つ必要です。
  3. Id、GUID、および人間が読める行識別子は、すべて異なる方法で処理する必要があります。

PKの最善のアプローチは何ですか?あなたがあなたの意見を正当化できればそれは素晴らしいでしょう。上記より良いアプローチはありますか?

編集:誰でも簡単にサンプル/アルゴリズムを使用して、適切にスケーリングできる行の人間が読める識別子を生成できますか?


1
これは主観的なものであるため、コミュニティWikiにする必要があります
John Sheehan

2
「主キーを構成する列が少なくとも3つあるはずです」?これは何を意味するのでしょうか?さらなる定義を提供できますか?それとも#3のこの部分ですか?
S.Lott、

@ S.Lott PK(NEWID(),NEWID(),NEWID());-)

@pst:なぜこれが要件なのですか?PKに3つの列が必要なのはなぜですか?なぜ1つまたは4つですか?
S.Lott、

3列のPKは次のように見えます。LocalID(自動インクリメントint)、GlobalID(GUID)、ForeignId(RolesTypeのような外部キー)など。LocalID+ ForiegnIdは複合キーの組み合わせである可能性があります。Guidは他のWebサイト/サービスに使用されます。個人的にはこれを行わず、Guid + ForiegnIdを使用します。
ジェラド2013

回答:


76

時々接続するアプリを使用してデータベース間で同期を行う場合は、プライマリキーにGUIDを使用する必要があります。デバッグは少し面倒なので、その場合を除いて、自動インクリメントのintに固執する傾向があります。

自動インクリメントint型は、デフォルトであるべきであり、ないそれらを使用することは正当化されるべきです。


3
GUIDは必要ありません。ステップを10または20に変更するか、将来的に同期する必要のある多くのサーバーを変更します。
ロバートC.バース

43
少なくとも90%の時間、GUIDは不要であり、スペースを無駄にします。
ジョナサンレフラー、

8
GUIDはやりすぎだと本気で思っています。私の主キーとしてGUIDを使用する必要はありませんでした。
Cyril Gupta、

7
または、スペースを無駄にしてGUIDとの衝突を危険にさらす代わりに、元の主キーと小さな識別子の複合キーを作成します。小さな識別子は同期ソースごとに異なります。
L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳

5
ISO国や言語コードなどの公開識別子が利用可能な場合でも、私がすべての場所でGUIDを使用していた店。そして、ブール値でCHAR(1)も十分だったとしても、のようにsex。言うまでもなく、それは作業するのに悪夢でした。
ルミ、

56

本当に基本的なポイント(と私が考えるもの)を指摘する答えがありません。つまり、主キーは、同じ実世界のエンティティに対してテーブルに2つのエントリが取得されないことを保証するものです(データベースでモデル化された)。この観察は、主キーの良い選択と悪い選択を確定するのに役立ちます。

たとえば、(米国)州の名前とコードの表では、名前またはコードのいずれかが主キーである可能性があります-それらは2つの異なる候補キーを構成し、それらの1つ(通常はより短い-コード)が主キー。機能依存関係(および結合依存関係-1NFから5NFまで)の理論では、主キーではなく重要なのは候補キーです。

反例として、人間の名前は一般的に主キーの悪い選択になります。「ジョン・スミス」や他の似たような名前で行く人はたくさんいます。ミドルネームを考慮に入れても(覚えておいてください:誰もが持っているわけではありません-たとえば、私は持っていません)、複製の余地はたくさんあります。したがって、人々は主キーとして名前を使用しません。彼らは社会保障番号(SSN)や従業員番号などの人工的な鍵を発明し、それらを使用して個人を指定します。

理想的な主キーは、短く、ユニークで、覚えやすく、自然なものです。これらの特性のうち、一意性は必須です。実際のデータの制約を考えると、残りは柔軟でなければなりません。

したがって、特定のテーブルの主キーを決定する場合は、そのテーブルが何を表しているかを調べる必要があります。テーブル内の列値のセットは、テーブル内の各行を一意に識別しますか?それらは候補キーです。さて、各候補キーが4列または5列で構成されている場合、それらが(主に短さを理由に)良い主キーを作成するには不格好であると判断するかもしれません。そのような状況では、代理キー(人工的に生成された番号)を導入する場合があります。多くの場合(常にではありませんが)、代理キーには単純な32ビット整数で十分です。次に、この代理キーを主キーとして指定します。

しかし、あなたがしなければならない通常の列のものをセットにユニーク制約を置くことによって-まだ他の候補キーことを確認してください(代理キーのためにあまりにも候補キーと同様に、選ばれた主キーです)、すべての一意の識別子として維持されます。

行を一意にするものを特定するのが難しい場合がありますが、単に情報を繰り返すだけではそれが真にならないため、何かを行う必要があります。また、注意していないと同じ情報を格納することを意図して2つ(またはそれ以上)の行を取得し、情報を更新する必要がある場合、1つの行だけを更新する危険性(特にカーソルを使用する場合)があります。すべての行ではなく、行が同期していないため、どの行に正しい情報が含まれているかは誰にもわかりません。

これは、いくつかの点で、かなり固い見方です。

必要なときにGUIDを使用しても特に問題はありませんが、GUIDは大きくなる傾向があり(16〜64バイトなど)、頻繁に使用されます。多くの場合、完全に適切な4バイト値で十分です。4バイトの値で十分なGUIDを使用すると、ディスク領域が無駄になり、インデックスページごとの値が少なくなるため、データへのインデックス付きアクセスも遅くなるため、インデックスはより深くなり、より多くのページを読み取る必要があります。情報。


10
米国の州名を使用したサンプルについては、コードがあなたの制御の及ばないものであるという理由だけで、別の代理キーを使用したいと思います。何らかの理由で変更する必要がある場合は、問題が発生します。
Dirk Vollmar、2009年

(続き)たとえば、ドイツは再統一後の1990年代に、4桁の郵便番号システムを5桁のシステムに置き換えました。
Dirk Vollmar、2009年

@divo:私は人工/代理キーの強力な擁護者ですが、4桁から5桁の郵便番号の変更が良い例であるとは思えません。郵便番号は、通常、何かのキーとしては使用されません。(そのコードについて何かを見つけるために最後にPostalCodeテーブルをクエリする必要があったのはいつですか?いいえ、他のテーブルで参照されることなく、アドレスの一部としてほとんど独占的に使用されています。あなたの提案は、アドレス自体の代理キー。)
ErikE 2010

@Emtucifor:はい、おそらくZIPは実際的な例ではありませんが、代理キーの一部が制御不能になり、何らかの理由で変更された場合、問題が発生するというのが私の指摘でした。誰かが新しい社会保障番号スキーム、新しいISSNスキーム、またはおそらくより現実的な-合併後に新しい製品IDシステムを作成し、従業員に新しい従業員番号を割り当てて成長を調整することなどを考えているとします。すべて架空の例にすぎませんが、ZIPを使用した以前の例が示すように、確立されたシステムが変更される場合があります。
Dirk Vollmar、2010

2
あなたの最初のポイントは正しいです。この制約には名前があります。これは「エンティティの整合性」と呼ばれます。EIでは、すべてのエンティティに一意のIDが必要です。自動番号が使用される場合を除いて、主キーは多くの場合、この要件を満たします。自動番号を使用すると、自動番号を除いて同一の2つの行を取得できます。これは通常、エンティティの整合性に違反します。
Walter Mitty

26

人々は普遍的な正しい答えを求めているので、これは宗教的な問題にすぎません。チームとこのSOスレッドの両方が非常に不一致を示しているという事実は、さまざまな状況で、説明したすべてのソリューションを使用する十分な理由があるという手がかりになるはずです。

  • 代理キーは、テーブル内の他の属性または属性セットが行を一意に識別するのに適していない場合に役立ちます。
  • テーブルをより読みやすくするために、可能な場合は自然キーが推奨されます。自然キーを使用すると、従属テーブルの外部キーにサロゲートIDではなく実際の値を含めることもできます。たとえば、state(CA、TX、NY)を格納する必要がある場合char(2)は、intではなく自然キーを使用することもできます。
  • 必要に応じて、複合主キーを使用します。id完全に適切な複合キーが存在する場合は、不必要に" "代理キーを追加しないでください(これは特に多対多のテーブルに当てはまります)。すべてのテーブルで3列のキーを使用することは絶対にナンセンスです。
  • GUIDは、複数のサイトで一意性を維持する必要がある場合のソリューションです。また、主キーの値を一意にする必要があるが、順序付けしたり連続したりする必要がない場合にも便利です。
  • INT対BIGINT:テーブル主キーに64ビットの範囲を必要とすることは一般的ではありません、64ビットハードウェアの可用性が高まっているため、負担になることはなく、オーバーフローしないことが保証されます。INTはもちろん小さいので、スペースが限られている場合は、わずかな利点があります。

6
人ができる限りそう思う。自然な鍵は恐ろしいです。データを変更したい場合はどうなりますか?ああ、できません。複合自然キーで結合を作成するのは面倒です。関連するすべてのテーブルにその複合キーを運ぶのは無駄です。
ロバートC.バース

2
@Robert:「ON UPDATE CASCADE」について読んでください。しかし、私はあなたの言っていることを理解し、属性は変更される可能性があり、一意ではないため、ほとんどの場合は代理キーを使用するのが最善であることに同意します。
ビルカーウィン

1
主キーは不変である必要があります。カスケード更新は、この場合の設計上の悪い決定に対する醜いハックにすぎません。自然キーは決して好まれません。ペストのように広がった複合キーと同じです。3か月以上のデータベース開発の経験がある人なら誰でもこれを知っているでしょう。
FDCastel 2009年

7
@FD:私はあなたの明確な声明に同意しません、そして私は1992年以来SQLデータベースで開発してきました。
ビルカーウィン

20

この種の情報のソースとして、データベースプログラマーのブログが好きです。

主キーの3列?列にはビジネスルールの要求に応じて適切な一意の制約を設定する必要があると思いますが、それでも別の代理キーがあります。複合キーは、ビジネスロジックがキーに入るという意味です。ロジックが変更されると、スキーマ全体が台無しになります。


2
:彼らは彼らのリンクを変更し、ここで更新ブックマークでdatabase-programmer.blogspot.com/2008/09/...
ブライアンRehbein

このようなプロジェクトを継承しただけです。そして、彼らが最初にやりたかったことは、スキーマを破壊しました。代理キーFTW。DB FTLのビジネスロジック。
Jason


11

少し話題から外れましたが、私はあなたと一緒にチャイムすることを強いられています...

主キーがGUIDの場合クラスター化インデックスにしないください。GUIDはシーケンシャルではないため、データはほぼすべての挿入中にディスク上で再配置されます。(うん。)GUIDを主キーとして使用する場合、それらは非クラスター化インデックスである必要があります。


1
非常に良い点-を区別するために1人のニーズLOGICAL主キー(複製が関与している場合は特に、そのためのGUIDを使用することが有効であるかもしれない)、との考え方PHYSICALなければならない-クラスタ化キーの概念NEVER GUIDことがないので、過度のインデックスの断片化につながります
marc_s 09/07/01

3
これは実際には正確ではありません。データは順番に挿入されます。GUIDのランダムな性質を考えると、テーブル全体のどこかにデータが配置される可能性があります。余裕がない場合は、ページ分割が発生しますが、「挿入ごとにディスク上で再配置」されることはありません。
ラルフシリントン

@ラルフ、あなたは正しい、すべての挿入ではありませんが、20倍のパフォーマンスヒットを引き起こすのに十分です。sql-server-performance.com/articles/per/…–
Portman、

SQL Server関数のnewsequentialid()は、GUIDを使用してインデックスの断片化の問題を解決します(グローバルな一意性が絶対に必要でない場合は、24バイトは依然として少し過剰です)。msdn.microsoft.com/en-us/library/ms189786.aspxを参照してください。
ErikE 2010

10

私は常に代理キーを使います。代理キー(通常はID列、自動インクリメント、またはGUID)は、データ自体にキーが存在しないキーです。一方、自然キーは、それ自体で行を一意に識別するキーです。私が人生で知ることができる限り、実際の自然の鍵はほとんどありません。米国のSSNのようなものでさえ、自然な鍵ではありません。複合主キーは、発生を待っている災害です。そのデータを編集することはできません(複合キーであるかどうかにかかわらず、自然キーの主な欠点です)。ただし、複合キーを使用すると、関連するすべてのテーブルにそのキーデータを永続化する必要があります。なんと巨大な無駄。

ここで、代理キーを選択するために、ID列を使用します(主にMS SQL Serverで作業します)。GUIDのはあまりにも大きく、マイクロソフトが推奨していますに対して PKとしてそれらを使用します。複数のサーバーがある場合、必要なのは、増分を10または20、または同期/拡張する必要があるサーバーの最大数と思われる数を増やし、後続の各サーバーの各テーブルのシードを追加することだけです。 、そしてあなたは決してデータの衝突を持つことはないでしょう。

もちろん、増分のため、ID列をBigInt(そうでなければlong [64ビット]とも呼ばれます)にします。

少し計算すると、増分を100にしても、テーブルに92,233,720,368,547,758(> 92兆)行ある可能性があります。


9

「プライマリ」キーというフレーズでの「プライマリ」という言葉の使用は、本当の意味では誤解を招くと思います。

まず、「キー」はテーブル内で一意でなければならない属性または属性セットであるという定義を使用します。

次に、任意のキーを持つことは、いくつかのしばしば相互に矛盾する目的に役立ちます。

  1. この親テーブルと関係がある子テーブルの1つ以上のレコードに対して結合条件として使用する。(これらの子テーブルで外部キーを明示的または暗黙的に定義する)
  2. (関連)子レコードが親タブに親レコードを持っていることの確認; e(子テーブルFKが親テーブルのキーとして存在している必要があります)
  3. テーブル内の特定のレコード/行をすばやく見つける必要があるクエリのパフォーマンスを向上させるため。

  4. 同じ論理エンティティを表す重複行がテーブルに挿入されないようにして、データの一貫性を確保します。(これは「自然な」キーと呼ばれることが多く、比較的不変のテーブル(エンティティ)属性で構成される必要があります。)

明らかに、意味のない、非自然なキー(GUIDや自動生成された整数など)は、完全に#4を満たすことができません。

しかし、多くの(ほとんどの)テーブルでは、多くの場合、#4を提供できる完全に自然なキーは複数の属性で構成され、非常に広いか、非常に広いため、目的#1、#2、または#3に使用すると、受け入れられなくなります。パフォーマンスの結果。

答えは簡単です。両方を使う。他の子テーブルのすべての結合とFKに単純な自動生成の統合キーを使用しますが、データの整合性を必要とするすべてのテーブル(非常に少数のテーブルでは必要ありません)に、矛盾するデータ行の挿入を防ぐ代替の自然な一意のキーがあることを確認します。 ..さらに、常に両方がある場合、自然キーの使用に対するすべての反対意見(変更された場合はどうなりますか?それがFKとして参照されているすべての場所を変更する必要があります)は、そのためにそれを使用していないため、疑わしくなります。 ..一貫性のない重複データを避けるために、それをPKである1つのテーブルでのみ使用しています...

GUIDについては、インデックスでGUIDを使用するとインデックスの断片化を防ぐことができるため、GUIDの使用には十分注意してください。それらを作成するために使用される最も一般的なアルゴリズムは、GUIDの「ランダム」部分を最上位のビット位置に配置します...これにより、新しい行が追加されると、定期的なインデックスのデフラグ/再インデックスの要件が増加します。


SQL Server関数のnewsequentialid()は、GUIDのインデックスの断片化の問題を解決します(グローバルな一意性が絶対に必要でない場合は、24バイトはまだ少し過剰です)。msdn.microsoft.com/en-us/library/ms189786.aspxを参照してください。
ErikE 2010

おっと、私は16バイトと言うつもりでした。
ErikE 2010

8

してはいけないことの1つは、スマートキーを使用することです。これは、レコードに関する情報がキー自体にコード化されているキーであり、最終的にはあなたを噛みます。

私は1つの場所で作業しました。主キーは、文字と数字を組み合わせたアカウントIDでした。具体的なことは覚えていませんが、たとえば、特定のタイプのアカウントは600の範囲にあり、別のタイプのアカウントは400で始まります。顧客が両方を要求するまで、それは素晴らしいことでした仕事の種類。または彼らがした仕事の種類を変えた。

別の場所では、ツリー内の場所をレコードの主キーとして使用しました。したがって、次のようなレコードがあります。

Cat1.subcatA.record1
Cat1.subcatA.record2
Cat1.subcatB.record1
Cat2.subcatA.record1

もちろん、顧客が最初に望んだことは、ツリー内のアイテムを移動する方法でした。それが起こる前に、ソフトウェアのセット全体が死にました。

お願いします、維持しなければならないコードを書いているなら、スマートキーを使わないでください!


私は心から同意します。スマートキー=ダム。
ロバートC.バース

2
これは、自然なキーが馬鹿げているという意味ではありません。しかし良い点。

4

私は主キーとして自動インクリメントのファンです。私はこれが警戒犯であることを心の中で深く知っていますが、追加されたとき(ORDER BY ID DESC、f'rインスタンス)によってデータをソートすることをとても簡単にします。

3つの列は、人間が解析するには非常に厳しい音に聞こえます。

そして、それはトレードオフです-リレーショナル機能のどれだけが必要なのか、このテーブルをここで質問する人間が理解できるようにすることです(ストアドプロシージャまたはプログラムインターフェイスではありません)。

自動インクリメントは私たち人間のためのものです。:-(


4

一般的には、状況によって異なります。

個人的には、autoincrement intが好きです。

しかし、私があなたに言えることの1つは、他のソースからのデータを鍵として決して信頼しないことです。私がやるたびに、それが私を噛むために戻ってくると誓います。まあ、二度と!


3

主キーを構成する列が少なくとも3つあるはずです。

分かりません。

「生の名前」や「生年月日」など、「自然な鍵」について話していますか?自然キーが存在する場合は理想的ですが、自然キーの候補のほとんどは、一意ではない(同じ名前の人が数人)か、一定ではありません(誰かが名前を変更できます)。

Int / BigIntは、自動インクリメントで十分な主キーです。

私はギドが好きです。自動インクリメントの潜在的な問題は、値(たとえば、「注文ID」)がデータベースインスタンス(たとえば、「販売データベース」)によって割り当てられることです。複数のデータベースインスタンスによって作成されたデータをマージする必要がある場合(たとえば、それぞれが独自のデータベースを持つ複数の営業所から)。


主キーは一意である必要がありますが、一定である必要はありません。したがって、「ON UPDATE CASCADE」で宣言された外部キー。ただし、主キーが一定であると仮定すると、多くのアプリケーションを簡略化するのに役立ちます。これは、代理キーの1つの利点です。
ビル・カーウィン

3

RE GUID

これが本当に本当に本当に大きなデータベース、大量の負荷、高速アクセスになるかどうか注意してください。

私の最後の仕事では、1億から5億レコードのデータベースがありましたが、データベースの担当者はGUIDに対して適切なサイズの10進数を強く主張しました。彼らは、(Oracleでは)文字列Guidの内部ストレージのサイズの違いと、10進数の値との比較では、ルックアップに非常に顕著な違いがあると感じていました。(より大きなキー=トラバースするより深い木)

GUIDのランダムな性質により、インデックスページのFILL FACTORも大幅に減少します。これにより、ティアリングとディスクI / Oが劇的に増加します。


「Fill-Factorを減らす」?それが何を意味するかわからないFill-factorは、インデックスが構築されたときにインデックスのリーフレベルで要求された空きスペースの割合として定義されるワンショット取引です。GUID値は、fill-factorが提供した空きスペースへの挿入のリーフレベルの幅全体にわたるランダムな性質の分布による。
ラルフシリントン、

1
GUIDが文字列になるのはいつからですか?GUIDは、適切なDBMSによって内部的に16バイトとして格納される必要があります。16進表記で32バイトとして格納することは無理でしょう。(またはダッシュで36、中括弧で38)
ErikE

2

列を自動インクリメントします。コードをSQL ServerまたはOracleとシームレスに連携させることができます。一方はIDを使用し、もう一方はシーケンスを使用してDALを介して動作します。私が同意するのは、レプリケーションを実行している場合や、後でデータを処理する際に受信するためにデータを送信している場合には、GUIDが必要になる場合があることです。


2

私は常に代理キーを使用してきました-「id」と呼ばれる自動インクリメント整数。別のオプションが明らかな場合でも、これを行う理由はたくさんあります。

  • 一貫性
  • データ非依存(一意であり、フォーマットの変更によって破棄されない)
  • 人間が読める

...そして次のことをしない合理的な理由はありません:

  • 結合のあいまいさ?-テーブルのエイリアシングは良い方法です、私見
  • 最適なテーブル?-エントリごとに1バイトを削除するのは時期尚早の最適化です。
  • テーブルごとの決定?-一貫性がなくなった
  • スケーリングの問題?-え?どうして?
  • 階層的なデータ構造?-それは非正規化であり、他のすべての宗教の主題です。理論的には私がいくつかの状況でファンであると言えば十分ですが、実際には決してありません:)

私がまだ考えていない、または出くわしていないことに対する賢明な理由はいつでも歓迎されます...


1

これは古典的な「それは依存する」です。すべてのプロジェクトに正しい答えはありません。状況に応じてさまざまなものが好きです。それは、ORMを使用しているかどうか、およびORMが何をサポートしているかによって異なります。それは全体的なアーキテクチャに依存します(分散されているかどうかなど)。うまくいくと思うものを1つ選んで、タブとスペースについて議論してください。


彼はまだそれがどのように依存するかを知りたいと思っています。これらを認識して初めて、自分の選択を信頼できるようになります...
ニコラス・レナード

1

サイズ、接続する人数、および複数のデータベースサーバーの状況に応じて、オプション#1または#3を使用する傾向があります。

オプション#2は私にはあまり意味がありません。3つのうちのいずれか1つでも一意のレコードを特定するのに十分ではない場合、2つのレコードが3つの列すべてに同じ値で表示される可能性があります(余分な操作を行わなくても)。3つの組み合わせに一意性を適用したい場合は、それらのインデックスを追加するだけです。


1

自動インクリメントのintまたはGUIDのみを使用しています。自動インクリメントintを使用した時間の99%。これは、データベースについて初めて知り、データベースを使用しない理由に遭遇したことがないときに使用するように教えられたものです(GUIDの方が優れている理由は知っていますが)。

自動インクリメントintは読みやすさを向上させるため、私は好きです。たとえば、「レコード129383を見てください」と言うと、だれかが簡単に見つけて見つけることができます。GUIDを使用すると、ほとんど不可能です。


2
どうしてそんなこと言うの?多くの人が自動インクリメント整数を使用しているようです。それが機能し、必要なものに対して適切に機能する場合は、それほど悪くはありません。
dtc

1

基本的な定義の答えを過ぎて、良い主キーを構成するものは、主に宗教と部屋の議論を断ち切ることに任されています。常に、今後もそうであるようなものがある場合は、個々の行に一意にマップすることで、主キーとして適切に機能します。その時点を過ぎると、他の考慮事項があります。

  • 主キーの定義は過度に複雑ではありませんか?「ベストプラクティス」に従うために不必要な複雑さを導入することを避けていますか?
  • データベースが処理するオーバーヘッドが少なくて済む、より優れた主キーはありますか(例:INTEGERとVARCHARなど)?
  • 私の主キーの一意性と定義済みの不変量が変更されないことは間違いありませんか?

この最後の1つは、GUID、自己インクリメントの整数列などを使用するようにほとんどの人々を惹きつけるものです。住所、電話番号、姓名などに依存しているだけでは、それを切り取らないからです。私が考えることができる人についての唯一の不変はSSNですが、私はそれらが永遠にユニークであり続けることについて100%さえ確信していません。

うまくいけば、これはいくつかの明確さを追加するのに役立ちます...


SSNが一意でないいくつかの歴史的なケースがあります。
ビル・カーウィン

1

私が主キーにアプローチする方法(そして私は最高だと感じています)は、「デフォルト」のアプローチを避けることです。これは、自動インクリメントする整数をたたいて、1日で呼び出すのではなく、問題を見て、「常に不変で変更されない列または列のグループはありますか?」と言います。答えが「はい」の場合、そのアプローチをとります。


それは、「できる限り整数の自動インクリメントを回避する」という意味ですか?私の理解では、業界の専門家は、大規模データベースでの最高のパフォーマンスは、最小限の署名、インデックス付きの増分単一列PKから得られると考えていました。
Hardryv 2010

1
私はいつも、エキスパートが仕事に最適なツールを使用すると思っていました
Andrew G. Johnson

1

ほとんどの場合整数です。

それらには、処理するのに小さい/速い以外に、他の良い理由があります。「404040」と「3463b5a2-a02b-4fd4-aa0f-1d3c0450026c」のどちらを書き留めますか?


後者は整数で、ダッシュが追加され、基数は16になります。ただし、404040は長いGUIDよりも処理が高速です。また、0は1ビットのデータを必要としないため、処理がさらに高速になります。
ストレッジャー、

1

わずかに関連性がありますが、小さな分類テーブル(基本的にコードでENUMを表すもの)があるときに最近始めたのは、主キーをchar(3)またはchar(4)にすることです。次に、これらの主キーをルックアップ値を表します。

たとえば、社内の販売代理店の見積もりシステムがあります。すべての見積品目に次のいずれかが割り当てられる「コストカテゴリ」があります...したがって、「tCostCategories」というタイプのルックアップテーブルがあり、主キーは「MTL」、「SVC」、「TRV」、「TAX」、 「ODC」。ルックアップテーブルの他の列には、コードの通常の英語の意味、「材料」、「サービス」、「旅行」、「税金」、「その他の直接費用」などの詳細が格納されます。

これはintよりも多くのスペースを使用しないため、本当に便利です。ソースデータを表示しているときに、値が何であるかを知るためにルックアップテーブルをリンクする必要はありません。たとえば、見積もり行は次のようになります。

1 PartNumber $ 40 MTL
2 OtherPartNumber $ 29.99 SVC
3 PartNumber2 $ 150 TRV

intを使用してカテゴリを表し、すべての行で1、2、3をリンクする方がはるかに簡単です。目の前にデータがあり、パフォーマンスはまったく影響を受けていないようです(私はそうではありません)本当にテスト済みです。)

本当の質問に関する限り...私はRowGUID uniqueidentifiersが好きです。私はこれについて100%ではありませんが、とにかくすべての行に内部RowGuidがあるわけではありませんか?その場合、RowGuidを使用すると、実際にはint(またはそのほかのこと)に比べてスペースが少なくて済みます。私が知っているのは、M $がGreatPlainsで使用するのに十分であれば、それで十分です。(カモにすべきか?)


1

GUIDを使用するもう1つの理由-階層データ構造を使用します。つまり、主キーが一致する「会社」という表と「ベンダー」という表があります。しかし、会社から「継承」するテーブル「メーカー」も持っています。ベンダーとメーカーに共通のフィールドはこれらのテーブルには表示されません-それらは会社に表示されます。この設定では、intの使用はGuidsよりもはるかに困難です。少なくとも、ID主キーは使用できません。


1
はい、できます。サブタイプテーブルにidentityプロパティを持たせず、スーパータイプテーブルの値を明示的に挿入します。stackoverflow.com/questions/2112882/…を
ErikE

1

信頼できるときはいつでも、自然な鍵が好きです。主題の専門家に意味のあるキーを使用するために、パフォーマンスの価格を少しでも支払うことをいとわない。

エンティティを説明するテーブルの場合、人々が行う主題と同じ方法で個々のインスタンスを識別する単純な自然キーが必要です。主題にエンティティの1つに対する信頼できる識別子がない場合は、代理キーを使用します。

関係を説明するテーブルでは、複合キーを使用します。各コンポーネントは、関係に参加するエンティティを参照するため、エンティティテーブルの行を参照します。繰り返しになりますが、複合キーを使用した場合のパフォーマンスへの影響は通常最小限です。

他の人が指摘したように、「主キー」という用語は少し誤解を招きます。リレーショナルデータモデルでは、使用される用語は「候補キー」です。1つのテーブルに複数の候補キーが存在する可能性があります。論理的には、それぞれが他と同じくらい優れています。それらの1つを「プライマリ」として選択し、そのキーを介してすべての参照を作成することは、設計者ができる選択です。


信頼できる自然キーのサンプルをいくつか教えてください。
ErikE 2010

1
「信頼できる」それ自体は鍵の特性ではありません。むしろ、それはデータを提供する人々の文脈における鍵と関係があります。実際にデータを管理する誰かに販売するアプリを作成している場合、どのキーがクライアントに信頼できるかを推測する必要があります。クライアントの多様性を考えると、ほとんど確実にクライアントの一部を間違えることになります。
Walter Mitty、2010

以上のことを踏まえて、私たちが以前に信頼していた鍵の例を次に示します。コースに関するデータベースがありました。これには、コース、スケジュールされたコースの提供、コースを教える資格のあるインストラクター、コースの前提条件、授業料などに関する教科書やその他のコース資料が含まれていました。コース開発によって新しいコースが作成されたとき、彼らが最初に行ったのはコースコードを割り当てることでした。彼らは、コースコードが一意であること、およびコースが割り当てられた後にコードを変更しないことを確認する責任がありました。それは私たちに与えられたデータの一部でした。
Walter Mitty

信頼できる自然キーのもう1つの良い例は、VIN(車両識別番号)です。この数年間、新品として販売されたすべての車両にはVINが付いています。彼らはユニークで不変であると信頼することができます。
Walter Mitty、2010

1

Guids.period。

スケールアウトする必要がある場合、または別の方法で主キーを割り当てる必要がある場合、それらはあなたの友達になります。他のすべてのインデックスを追加できます。


私の声明を明確にするために更新します。

私はさまざまな種類のサイトに取り組んできました。小規模な単一サーバーから、複数のDBサーバーとWebサーバーでサポートされる大規模サーバーまで。確かに、自動インクリメントのintを主キーとするだけで問題がなかったはずのアプリがありました。しかし、それらは私のやり方のモデルに適合しません。

GUIDを使用する場合は、どこにでもIDを生成できます。リモートサーバー、Webアプリ、データベース自体、またはマルチマスターの状況では複数のデータベース内で生成される可能性があります。

一方、自動インクリメントされたINTは、プライマリデータベース内でのみ安全に生成できます。繰り返しになります、この1つのバッキングDBサーバーに密接に結び付けられ、スケールアウトが気になるものではないアプリケーションがある場合、これ問題ありません。

確かに、GUIDを使用すると、毎晩再インデックス処理を行う必要があります。ただし、自動インクリメントINT以外を使用している場合は、とにかくそれを行う必要があります。INTをプライマリとして使用しても、断片化に対処するために再生成が必要な他のインデックスがある可能性があります。したがって、GUIDを使用しても、それらのタスクは関係なく実行する必要があるため、別の問題が正確に追加されるわけではありません。

そこにある大きなアプリを見ると、何か重要なことがわかります。それらはすべて、Base64でエンコードされたGUIDをキーとして使用しています。この理由は単純です。GUIDを使用すると、簡単にスケールアウトできますが、INTをスケールアウトしようとすると、多くのフープが飛び越えてしまう可能性があります。

最新のアプリは、約1か月続く大量の挿入の期間を通過します。その後、90%以上のクエリがすべてレポート用に選択されています。容量を増やすために、この大きな挿入期間中に追加のDBサーバーを起動できます。後でそれらをレポート用に単一のDBに簡単にマージします。INTでそれを試みるのは絶対的な悪夢です。

率直に言って、データベースをクラスター化したり、レプリケーションをセットアップしたりするときはいつでも、DBサーバーはとにかくテーブルにGUIDがあることを要求します。したがって、システムを拡張する必要があると思われる場合は、適切なシステムを選択してください。


インデックスのFILL FACTORを調べたことがありますか?GUIDのランダムな性質はスイスチーズを作ります-それらの効果を劇的に減らします。
stephbu

2
"Guids.period":それは間違っています。適切な場合はGUIDを使用する必要があります。他のコメンターが指摘したように、それはプログラマーとしての生活を楽にするかもしれませんが、DBの全体的なサイズとパフォーマンスに影響を与えます。
ミッチウィート

結局、問題なくアプリを複数のデータベースサーバーにスケールアウトできます。しかし、皆さんは小さなサイトで作業していると思います。
NotMe

3
論理プライマリキーの場合はGUIDでも問題ないかもしれませんが、GUID列をCLUSTERINGキーとして使用することは決してありません。インデックスの断片化に
悩まされ、

私は確かに「Guids.period」を宣言しません。このトピックについて-実際には、業界でも非常にぎこちない「ベストプラクティス」の種類のステートメントがあるため、デフォルトでは(特にそのステートメントに関して)不安定な状況に置かれます。GUIDと同じくらい苦痛なことは、正当な根拠が必要であり、JLが言うように、私たちのほとんどはそれを最後の手段と考えるでしょう。スレッドの残りを読まずに投稿したかのようです。
Hardryv 2010

0

これは、あなたが気づいたかどうかにかかわらず、複雑なテーマです。このStackOverflow FAQのセクションに該当する場合があります。

ここではどんな質問をしてはいけませんか?

主観的、議論的、または長期にわたる議論を必要とする質問をしないでください。質問に答えられる場所です!

これは何年もの間議論されてきました、そして何年もの間議論され続けます。私が見たコンセンサスの唯一のヒントは、OOガイ(GUIDが唯一の方法です!)、データモデラー(自然キーが唯一の方法です!)またはパフォーマンス指向のDBA(INTが唯一の方法です!)。


議論は長くはしません。一般的なコンセンサスを知りたくてたまらなかった。
Perpetualcoder

1
私はあなたが望むどんな質問をしても言う!そうでなければ、このコミュニティは静的になり、ウィキペディアがそうであるように過剰に制御されます。あなたが尋ねることを何でも選ぶように人々に尋ねさせる必要がある時のように私には思えます。それらを信頼しなさい、そうすれば彼らは彼ら自身を信頼するようになるかもしれない!
Nicholas Leonard、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.