web-dev-qa-db-ja.com

常に自動インクリメント整数の主キーを持つことは良い習慣ですか?

私のデータベースでは、特定の行を一意に検索できるように、作成するすべてのテーブルにidという名前の自動インクリメント整数主キーを使用する傾向があります。

これは悪い考えだと思いますか?この方法でそれを行うことに欠点はありますか? id, profile_id, subscriptionsのような複数のインデックスが時々あります。ここで、idは一意の識別子、profile_ididテーブルの外部Profileへのリンク、等.

または、そのようなフィールドを追加したくないシナリオはありますか?

198
AJJ

一意の行識別子が保証されていることは決して悪い考えではありません。絶対に言ってはいけないことだと思いますが、圧倒的な大部分の時間に行きましょう。

理論的な潜在的な欠点には、維持する追加のインデックスと使用される追加のストレージ領域が含まれます。それを使用しない理由は、これだけでは十分ではありません。

138
GrandmasterB

以前はすべての答えに同意しません。すべてのテーブルに自動インクリメントフィールドを追加するのが悪い理由はたくさんあります。

明らかなキーがないテーブルがある場合は、自動インクリメントフィールドを使用することをお勧めします。結局のところ、select * from blog where body = '[10000 character string]'を使いたくないのです。むしろselect * from blog where id = 42。これらのほとんどの場合、本当に必要なのは一意の識別子であると私は主張します。連続した一意の識別子ではありません。代わりに、普遍的に一意の識別子を使用することをお勧めします。

ほとんどのデータベースには、ランダムな一意の識別子を生成する関数があります(mysqlではuuid、mssqlではnewid)。これらを使用すると、異なるマシン上の複数のデータベースに、ネットワーク接続なしでいつでもデータを生成でき、データを競合なしでマージできます。これにより、複数のサーバーや、たとえばマイクロサービスなどのデータセンターをより簡単にセットアップできます。

これにより、攻撃者がアクセスしてはならないページのURLを推測することも回避されます。 https://example.com/user/1263がある場合は、おそらくhttps://example.com/user/1262もあるでしょう。これにより、ユーザープロファイルページのセキュリティエクスプロイトを自動化できます。

また、uuidカラムが役に立たない場合や有害な場合も多くあります。あなたがソーシャルネットワークを持っているとしましょう。 usersテーブルとfriendsテーブルがあります。 friendsテーブルには、2つのuserid列と自動インクリメントフィールドが含まれています。 35と友達にしたいので、3,5をデータベースに挿入します。データベースは自動インクリメントIDを追加し、1,3,5を格納します。どういうわけか、ユーザー3は[友達を追加]ボタンをもう一度クリックします。 3,5をデータベースに再度挿入すると、データベースによって自動インクリメントIDが追加され、2,3,5が挿入されます。しかし、今では35は2回お互いに友達になりました!これはスペースの浪費です。考えてみれば、自動インクリメントカラムも同様です。 abが友だちかどうかを確認するには、これら2つの値を持つ行を選択するだけです。これらは一緒に、一意の行識別子です。 (おそらく、3,55,3が重複排除されるようにするためのロジックを記述したいと思うでしょう。)

Url-shortenerを作成するときなど、シーケンシャルIDが役立つケースはまだありますが、ほとんどの場合(URLショートナーを使用しても)、ランダムに生成された一意のIDが実際に代わりに使用したいものです。

TL; DR:各行を識別する一意の方法がない場合は、自動インクリメントではなくUUIDを使用します。

95
Filip Haglund

自動インクリメンタルキーには主に利点があります。

しかし、考えられるいくつかの欠点は次のとおりです。

  • ビジネスキーがある場合は、ビジネスルールを適用するために、その列にも一意のインデックスを追加する必要があります。
  • 2つのデータベース間でデータを転送する場合、特にデータが複数のテーブル(つまり、マスター/詳細)にある場合、データベース間でシーケンスが同期されないため、簡単ではありません。最初に、次を使用して等価テーブルを作成する必要があります。 OriginデータベースのどのIDがターゲットデータベースのどのIDに対応するかを知るための一致としてのビジネスキー。ただし、分離されたテーブルとの間でデータを転送する場合は問題ありません。
  • 多くの企業には、アドホックでグラフィカルなポイントアンドクリックのドラッグアンドドロップレポートツールがあります。自動インクリメンタルIDは意味がないので、このタイプのユーザーは「アプリ」の外部のデータを理解するのが難しいと感じるでしょう。
  • ビジネスキーを誤って変更した場合、人間が識別できるものがないため、その行を回復できない可能性があります。 これにより、BitCoinプラットフォームで一度障害が発生しました
  • 一部の設計者は、PKを単に2つの外部IDで構成する必要がある場合に、2つのテーブル間の結合テーブルにIDを追加します。明らかに、結合テーブルが3つ以上のテーブルの間にある場合、自動インクリメンタルIDは理にかなっていますが、FKの組み合わせに適用するときに一意のキーを追加してビジネスルールを適用する必要があります。

Wikipediaの記事のセクションはこちら 代理キーの欠点について。

61

逆に言えば、いいえ。常にAutoInc PKの数値を持っている必要はありません。

データを注意深く分析すると、データ内の自然なキーを特定することがよくあります。これは、データがビジネスにとって本質的な意味を持つ場合によく見られます。 PKは、ビジネスユーザーがシステムの属性を説明するための第2言語として使用する、古代のシステムのアーティファクトである場合があります。たとえば、車両管理システムで「車両」テーブルの主キーとして使用される車両のVIN番号を見てきました。

ただし、それが作成されたものであり、すでに一意の識別子がある場合は、それを使用してください。意味のない2番目の主キーを作成しないでください。それは無駄であり、エラーを引き起こす可能性があります。

AutoInc PKを使用して、顧客にとって意味のある値を生成できる場合があります。ポリシー番号。開始値を適切な値に設定し、先行ゼロなどに関するビジネスルールを適用します。これは、おそらく「両方の長所」のアプローチです。

比較的静的な値が少ない場合は、システムユーザーにとって意味のある値を使用してください。 L、C、Hを使用できる場合に1,2,3を使用する理由L、H、Cは保険の「保険契約タイプ」のコンテキストで生命、自動車、住宅を表すか、またはVINの例に戻って、「TO 「トヨタにとって?すべてのToyata車には、「TO」で始まるVINがあります。これは、ユーザーが覚えておかなければならないことが1つ少なくなり、プログラミングエラーやユーザーエラーが発生する可能性が低くなり、管理レポートの完全な説明の代用にもなり、レポートが簡単になります書くこと、そしておそらく生成するのがより速い。

これのさらなる開発はおそらく「橋が遠すぎる」であり、私は一般にそれをお勧めしませんが、完全にするためにそれを含めて、あなたはそれの良い使用法を見つけるかもしれません。つまり、説明を主キーとして使用します。急速に変化するデータにとって、これは嫌悪です。 veryAll The Timeでレポートされる静的データの場合、そうではない可能性があります。言及するだけで、可能性としてそこに座っています。

私はAutoInc PKを使用しています。頭を使って、より良い代替案を最初に探します。データベース設計の芸術は、迅速に照会できる意味のあるものを作っています。結合が多すぎると、これが妨げられます。

編集自動生成されたPKが不要なもう1つの重要なケースは、他の2つのテーブルの共通部分を表すテーブルの場合です。車のアナロジーに固執するために、車には0..nのアクセサリーがあり、各アクセサリーは多くの車にあります。これを表すには、CarおよびAccessoryのPKと、日付などのリンクに関するその他の関連情報を含むCar_Accessoryテーブルを作成します。

(通常)必要としないものは、このテーブルのAutoInc PKです。これは、車からのみアクセスできます。「この車に付属しているアクセサリーを教えて」または「この車のアクセサリーを教えて」

20
mcottle

多くのテーブルにはすでに固有のIDがあります。これらのテーブルに別の一意のID列(自動インクリメントなど)を追加しないでください。代わりに、自然な一意のIDを使用してください。別の一意のIDを追加すると、基本的にデータに冗長性(重複または依存関係)が生じます。これは正規化の原則に反します。 1つの一意のIDは、正確さのために他のIDに依存しています。これは、これらの行を管理するすべてのシステム常時で完全に同期している必要があることを意味します。これは、長期にわたって管理および検証する必要が本当にない、データ整合性のもう1つの脆弱性です。

最近のほとんどのテーブルでは、一意のid列を追加することによるパフォーマンスのわずかな向上は実際には必要ありません(場合によっては、パフォーマンスが低下することもあります)。 ITの一般的なルールとして、plague!のような冗長性は避けてください。それは拒絶反応です。そして、引用に注意してください。すべては可能な限り単純でなければなりませんが、単純ではありません。自然なものが整然としていないように見えても、1つで十分な2つの一意のIDは使用しないでください。

12
Brad Thomas

大規模なシステムでは、IDは整合性ブースターです。どこでもalmost使用してください。このコンテキストでは、個々の主キーはお勧めできません。最終的には高価です(理由をお読みください)。

すべてのルールには例外があるため、エクスポート/インポートに使用されるステージングテーブル、および同様の一方向テーブルまたは一時テーブルでは、整数の自動インクリメントIDは必要ない場合があります。分散システムでは、IDではなくGUIDを使用することもできます。

ここでの多くの回答は、既存の一意のキーを取得する必要があることを示唆しています。まあ150文字でも?私はそうは思いません。

今私の主なポイント:

自動インクリメント整数IDの反対者は、最大20のテーブルを持つ小さなデータベースについて話しているようです。そこでは、各テーブルに個別のアプローチをする余裕があります。

ただし、ERP 400以上のテーブルで、任意の場所に整数の自動インクリメントIDがある場合(上記の場合を除く)ちょうど意味があります。他の一意のフィールドが存在し、一意性が確保されている場合でも、それらに依存することはありません。

  • 普遍的な時間節約、労力節約、覚えやすい慣習の恩恵を受けることができます。
  • ほとんどの場合、キーが何であるかを確認する必要なしに、テーブルをJOINします。
  • 整数の自動インクリメント列を操作するユニバーサルコードルーチンを使用できます。
  • 既存のテーブルのIDを参照するだけで、新しいテーブルまたはユーザープラグインでシステムを拡張することができます。それらは最初からすでに存在しており、追加するためのコストはかかりません。

大規模なシステムでは、これらの個々の主キーの小さな利点を無視して、ほとんどの場合、整数の自動インクリメントIDを一貫して使用する価値があります。既存の一意のフィールドを主キーとして使用すると、レコードあたり数バイトを節約できる可能性がありますが、今日のデータベースエンジンでは、追加のストレージまたはインデックス作成時間は問題ありません実際には、開発者/メンテナの無駄な時間で、はるかに多くのお金とリソースを失っています。今日のソフトウェアは、プログラマーの時間と労力に合わせて最適化する必要があります。一貫したIDを使用したアプローチは、はるかに優れています。

10
miroxlav

余分なデザインをすることは良い習慣ではありません。つまり-必要のないときに常に自動インクリメントの主キーを保持することはお勧めしません。

不要な例を見てみましょう。

記事のテーブルがあります。これには、int主キーid、およびtitleという名前のvarchar列があります。

また、記事のカテゴリの完全なテーブル–id int主キー、varchar nameもあります。

Articlesテーブルの1行にはid 5とtitle "バターでガチョウを調理する方法"があります。その記事を、Categoriesテーブルの次の行にリンクしたいとします。 "Fowl"(id:20)、 "Goose"(id:12)、 "Cooking" (id:2)、「バター」(id:9)。

これで、記事とカテゴリの2つのテーブルができました。どのようにして2つの関係を作成しますか?

Id(主キー)、article_id(外部キー)、category_id(外部キー)の3つの列を持つテーブルを作成できます。しかし、今あなたは次のようなものを持っています:

| id | a_id | c_id | 
 | 1 | 5 | 20 | 
 | 2 | 5 | 12 | 
 | 3 | 5 | 2 | 

より良い解決策は、2つの列で構成される主キーを持つことです。

| a_id | c_id | 
 | 5 | 20 | 
 | 5 | 12 | 
 | 5 | 2 | 

これを行うには、次のようにします。

create table articles_categories (
  article_id bigint,
  category_id bigint,
  primary key (article_id, category_id)
) engine=InnoDB;

自動インクリメント整数を使用しないもう1つの理由は、主キーにUUIDを使用している場合です。

UUIDはその定義から一意であり、一意の整数を使用するのと同じことを実現します。また、整数よりも独自の利点(および短所)があります。たとえば、UUIDを使用すると、参照している一意の文字列が特定のデータレコードを指すことがわかります。これは、1つの中央データベースがない場合、またはアプリケーションがデータレコードをオフラインで作成できる(後でデータベースにアップロードできる)場合に便利です。

結局のところ、主キーを1つのものとして考える必要はありません。それらを、それらが実行する機能と考える必要があります。なぜ主キーが必要なのですか?将来変更されないフィールドを使用して、テーブルから特定のデータセットを一意に識別できるようにするため。これを行うにはidという特定の列が必要ですか、またはこの一意の識別を他の(不変の)データに基づいて行うことができますか?

8
anw

自動インクリメント(ID)主キーは、データベースのコンテキストとそのデータベースの直接のクライアントの外では意味がないことに注意することを除いて、良い考えです。たとえば、一部のデータを別のデータベースに転送して保存し、その後、両方のデータベーステーブルに異なるデータを書き込む場合、IDは分岐します。つまり、1つのデータベースで42のIDを持つデータは、必ずしもデータと一致しませんもう一方のIDは42です。

このため、データベースの外部で行を一意に識別できるようにする必要がある場合(頻繁にそうである場合)、この目的のために別のキーが必要です。慎重に選択したビジネスキーで十分ですが、多くの場合、一意性を保証するために必要な列の数が多くなります。別の手法は、自動インクリメントのクラスター化された主キーとしてId列を持ち、クラスター化されていない一意のキーとして別のuniqueidentifier(guid)列を持つことです。この場合でも自動インクリメントキーが存在する理由は、自動インクリメントキーをクラスタ化してインデックスを作成する方が、GUIDに対して同じことを行うよりも効率的だからです。

自動インクリメントキーが不要な1つのケースは、主キーが他の2つのテーブルのId列の複合である多対多のテーブルです(ここでも自動インクリメントキーを使用できますが、それの要点がわからない)。

もう1つの質問は、自動インクリメントされたキーのデータ型です。 Int32を使用すると、値の範囲は大きくなりますが、比較的制限されます。個人的には、値が不足することを心配する必要がないように、idにbigint列を頻繁に使用しています。

7
MatthewToday

または、そのようなフィールドを追加したくないシナリオはありますか?

承知しました。

まず第一に、自動インクリメントを持たないデータベースがあります(たとえば、Oracleは確かに最も小さな候補の1つではありません)。これは、誰もがそれらを好きまたは必要とするわけではないという最初の兆候であるはずです。

さらに重要なのは、IDが実際に何であるかを考えることですis-これはデータの主キーです。異なる主キーを持つテーブルがある場合、IDは不要であり、IDは必要ありません。たとえば、テーブル(EMPLOYEE_ID, TEAM_ID)(各従業員が同時に複数のチームに所属できる場合)には、これら2つのIDで構成される主キーが明確に定義されています。このテーブルの主キーでもあるautoincrement ID列を追加しても、まったく意味がありません。今、あなたは2つの主キーを持ち歩き、「主キー」の最初のWordはあなたが本当に1つしか持つべきではないというヒントを与えます。

7
AnoE

私は通常、「長寿命」データ(一度挿入すると予想されるレコード)に新しいテーブルを定義するときに、「ID」列(自動インクリメント整数)を使用して、ビットフィールドを設定することで「論理的に削除」されても無期限に保持します)。

それらを使用したくないときに考えられる状況はいくつかありますが、そのほとんどは、DBの1つのインスタンスの1つのテーブルを新しいID値の信頼できるソースにすることができないシナリオに要約されます。

  • 増分IDは潜在的な攻撃者にとって情報が多すぎる場合。「公開されている」データサービスにID列を使用すると、「ドイツ戦車の問題」に対して脆弱になります。レコードID 10234が存在する場合は、レコード10233、10232などが存在し、少なくともレコード10001に戻っていることが理にかなっています。その後、レコード1001、101、1をチェックして、ID列がどこから始まったかを簡単に確認できます。主にランダムなデータで構成されるV4 GUIDは、このインクリメンタルな動作を意図的に壊すため、GUIDが1つ存在するだけで、GUIDのバイトをインクリメントまたはデクリメントして作成されたGUIDは必ずしも存在しません、攻撃者が単一レコードの取得を目的としたサービスをダンプツールとして使用することを困難にします。アクセスをより適切に制限できる他のセキュリティ対策がありますが、これは役立ちます。
  • M:M相互参照表。これは一種のギミですが、私はそれが以前に行われたのを見ました。データベース内の2つのテーブル間に多対多の関係がある場合、主な解決策は、各テーブルのPKを参照する外部キー列を含む相互参照テーブルです。このテーブルのPKは、組み込みインデックスの動作を取得し、参照の一意性を確保するために、事実上常に2つの外部キーの複合キーである必要があります。
  • このテーブルで大量に挿入および削除することを計画している場合おそらく、ID列の最大の欠点は、別のテーブルまたはクエリから行を挿入するときに実行する必要がある余分なフープラです。元のテーブルのキー値を維持する場所。 「ID挿入」をオンにする必要があります(ただし、DBMSで行われます)。挿入するキーが一意であることを手動で確認し、インポートが完了したら、IDカウンターを存在する最大値へのテーブルのメタデータ。この操作がこのテーブルで頻繁に発生する場合は、別のPKスキームを検討してください。
  • 分散テーブルの場合 ID列は、単一インスタンスのデータベース、フェイルオーバーペア、および1つのデータベースインスタンスがいつでもデータスキーマ全体に対する唯一の権限であるその他のシナリオに最適です。ただし、移動できるのは非常に大きいため、1台のコンピューターで十分な速度を維持できます。レプリケーションまたはトランザクションログ配布では、読み取り専用のコピーを追加できますが、そのソリューションの規模にも制限があります。遅かれ早かれ、2つ以上のサーバーインスタンスがデータの挿入を処理し、相互に同期する必要があります。ほとんどのDBMSは、インスタンス固有の識別子として生成するGUIDの一部を使用するように事前に構成されており、残りのインスタンスを生成するため、そのような状況になると、増分フィールドではなくGUIDフィールドが必要になります。ランダムまたは増分のいずれかの識別子。どちらの場合でも、2つのGUIDジェネレーター間の衝突の確率はゼロですが、ID整数列はこの状況で管理するのが悪夢です(シードをオフセットして増分を2に設定することにより、偶数/奇数に行くことができます)ただし、1つのサーバーで他のサーバーよりも多くのアクティビティが検出された場合は、IDを浪費しています。
  • DBの複数のテーブルに一意性を適用する必要がある場合たとえば、会計システムでは、総勘定元帳を管理するのが一般的です(これまでに発生したすべての口座の貸方または借方ごとに行が表示されます)なので、非常に急速に大きくなります)。それぞれが1暦月/年を表す一連のテーブルとして。次に、ビューを作成して、それらをレポート用にフックできます。論理的には、これはすべて1つの非常に大きなテーブルですが、細かく分割することで、DBのメンテナンスジョブが簡単になります。ただし、複数のテーブルへの挿入を管理する方法(次の月にトランザクションのロギングを開始しながら、最後のトランザクションをクローズできるようにする方法)が、重複するキーに終わらないという問題があります。繰り返しになりますが、DBMSは真にユニークな方法でこれらを生成するように設計されているため、ID整数列の代わりにGUIDが主なソリューションとなり、単一のGUID値がDBMS全体で一度だけ表示されます。 。

これらの状況でID列を使用できるようにする回避策はありますが、前述のとおりですが、ほとんどの場合、ID列からGUIDにアップグレードする方が簡単で、問題をより完全に解決します。

7
KeithS

他の人がインクリメントする主キーを主張しているので、GUIDの主キーを作成します。

  • 一意であることが保証されています
  • アプリケーション内のデータのためにデータベースにアクセスする回数を1回減らすことができます。 (たとえば、typesテーブルの場合、GUIDをアプリケーションに格納し、それを使用してレコードを取得できます。IDを使用する場合、名前でデータベースにクエリを実行する必要があります。これを実行してPKを取得し、後で再度照会して完全な詳細を取得するアプリケーション)。
  • データを非表示にするのに便利です。 www.domain.com/Article/2 www.domain.com/article/b08a91c5-67fc-449f-8a50-ffdf2403444aは何も教えていないのに対し、あなたは2つの記事しかないことを知らせます。
  • 異なるデータベースのレコードを簡単にマージできます。
  • MSFTはIDにGUIDSを使用します。

編集:ポイントの複製

6

質問と多くの回答は、各テーブルのすべての自然キーがデータベースの論理スキーマにのみ存在し、それぞれのすべての代理キーが存在するという重要なポイントを逃していますテーブルは、データベースの物理スキーマにのみ存在します。他の回答では、整数キーとGUID代理キーの相対的な利点のみを取り上げ、代理キーが適切に使用される理由とその時期については触れていません。

ところで:不適切に定義された不正確な用語主キーの使用を避けましょう。これは、最初にリレーショナルモデルに(不適切に)オプトインされ、次にさまざまなRDBMSベンダーによって物理ドメインに再度オプトインされたリレーショナルデータモデルのアーティファクトです。その使用は、セマンティクスを混乱させるためにのみ役立ちます。

リレーショナルモデルから、データベース論理スキーマ最初の正規形になるように=、すべてのテーブルには、テーブルの各行を一意に識別するユーザーに表示されるフィールドのセット、自然キー、が必要です。ほとんどの場合、そのような自然キーはすぐに識別されますが、タイブレーカーフィールドとしてであれ、そうでないものであれ、構築する必要がある場合があります。ただし、このような構築されたキーは常にユーザーに表示されるため、常にデータベースの論理スキーマに存在します。

対照的に、テーブルのサロゲートキーは、データベースの物理スキーマに純粋に存在します(したがって、常にセキュリティの両方のために理由と、データベースの整合性を維持するために、データベースユーザーには完全に見えないようにしてください)。 代理キーを導入する唯一の理由は、DBの物理的なメンテナンスと使用におけるパフォーマンスの問題に対処することです。それらが、結合、レプリケーション、データの複数のハードウェアソース、またはその他のものであるかどうか。

サロゲートキーの導入の唯一の理由はパフォーマンスであるため、パフォーマンスを向上させたいと考えます。パフォーマンスの問題が結合である場合は、代理キーをできるだけ狭くする必要があります(ハードウェアの邪魔にならないように、通常、短い整数とバイトは除外されます)。結合のパフォーマンスは最小のインデックスの高さに依存するため、4バイトの整数が自然な解決策です。パフォーマンスの問題が挿入率である場合は、4バイトの整数も自然な解決策になる場合があります(RDBMSの内部によって異なります)。テーブルのパフォーマンスの問題が、他の代理キーテクノロジよりもレプリケーションまたは複数のデータソースである場合は、GUIDまたは2つの部分からなるキー(ホストID +整数)の方が適しているかもしれませんが、私は個人的にGUIDを好きではありませんが、便利です。

要約すると、すべてのテーブルで代理キー(任意のタイプ)が必要になるわけではありません。これらは、検討中のテーブルのパフォーマンスに必要と思われる場合にのみ使用してください。どの共通代理キーテクノロジを使用するかに関係なく、選択する前にテーブルの実際のニーズについて慎重に検討してください。テーブルのサロゲートキーテクノロジの選択を変更すると、作業が煩雑になります。後継者が行った選択を理解できるように、テーブルの主要なパフォーマンスメトリックを文書化します。

特殊なケース

  1. ビジネス要件が監査(またはその他の)目的でトランザクションの連続番号を義務付けている場合、そのフィールドはnot代理キーです。 自然キーです(追加の要件があります)。ドキュメントから自動インクリメント整数は代理キーのみを生成するため、それを生成する別のメカニズムを見つけます。明らかに、ある種のモニターが必要になります。トランザクションを複数のサイトから調達している場合、指定されているため、1つのサイトはspecialになりますモニターのホストサイト

  2. テーブルが100行を超えることがない場合、インデックスの高さは関係ありません。すべてのアクセスはテーブルスキャンによって行われます。ただし、長い文字列での文字列比較は、4バイト整数の比較よりもはるかにコストがかかり、GUIDの比較よりもコストがかかります。

  3. char(4)codeフィールドをキーとするcode値のテーブルは、 1つは4バイト整数です。私にはこれの証拠はありませんが、私は仮定を頻繁に使用し、それを否定する理由がありませんでした。

2
Pieter Geerkens

優れた設計の原則として、すべてのテーブルには、行を一意に識別する信頼できる方法が必要です。それが主キーの目的ですが、常に主キーの存在を必要とするわけではありません。すべてのテーブルに主キーを追加することは、一意の行識別を提供するので、悪い習慣ではありませんが、必要ない場合があります。

2つ以上のテーブルの行間の信頼できる関係を維持するには、外部キーを介して行う必要があるため、少なくともいくつかのテーブルに主キーが必要です。すべてのテーブルに主キーを追加すると、新しいテーブルやリレーションシップを既存のデータに追加するときに、データベース設計を拡張しやすくなります。事前の計画は常に良いことです。

基本原則(おそらくハードルール)として、主キーの値はその行の存続期間を通じて変更されるべきではありません。行内のビジネスデータはその存続期間中に変更される可能性があると想定するのが賢明です。そのため、ビジネスデータは主キーの候補としては不十分です。これが、自動インクリメントされた整数のような抽象的なものがしばしば良い考えである理由です。ただし、自動インクリメントされた整数には制限があります。

データがデータベース内でのみ有効である場合、自動インクリメントされた整数で問題ありません。ただし、他の回答で述べたように、データの共有、同期、またはデータベース外でのライフを希望する場合、自動インクリメントされた整数は主キーとして不十分です。より良い選択は、guid(別名uuid "universally unique id")です。

2
Zenilogix