この質問はSOで何度も聞かれ、開発者とDBAの間(および開発者の間)で長年にわたって多くの議論の対象となってきました。
まず、あなたの質問の前提は、一方のアプローチがもう一方のアプローチよりも普遍的に優れていることを意味しているということから始めましょう...これは実際の生活ではめったにありません。代理キーと自然キーにはどちらにも用途と課題があります。それらが何であるかを理解することが重要です。システムでどちらを選択する場合でも、一貫性には利点があることに注意してください。これにより、データモデルが理解しやすくなり、クエリやアプリケーションの開発が容易になります。また、PKの場合、自然キーよりも代理キーを好む傾向があると言いたいのですが、それは、自然キーがその役割で役立つことがない場合があるという意味ではありません。
サロゲートキーと自然キーは相互に排他的ではなく、多くの場合、相互に補完できることを理解することが重要です。データベーステーブルの「キー」は、単にレコード(行)を一意に識別するものであることに注意してください。1つの行に、レコードを一意にするさまざまなカテゴリの制約を表す複数のキーを含めることは完全に可能です。
一方、主キーは、データベースが参照整合性を適用し、他のテーブルで外部キーを表すために使用する特定の一意のキーです。どのテーブルにも1つの主キーしか存在できません。主キーの本質的な品質は、100%一意であり、NULLではないことです。主キーの望ましい品質は、それが安定している(変わらない)ことです。変更可能な主キーは可能ですが、データベースに多くの問題を引き起こし、回避する方が適切です(カスケード更新、RI障害など)。テーブルに代理主キーを使用することを選択した場合は、自然キーの存在を反映するために一意の制約を作成することも検討する必要があります。
代理キーは、次の場合に役立ちます。
- 自然キーは安定していません(値は時間の経過とともに変化する可能性があります)
- 自然キーが大きいか扱いにくい(複数の列または長い値)
- 自然キーは時間の経過とともに変化する可能性があります(時間の経過とともに列が追加/削除されます)
すべての行に短く安定した一意の値を提供することで、データベースのサイズを縮小し、パフォーマンスを向上させ、外部キーを格納する依存テーブルの変動性を減らすことができます。キーポリモーフィズムの利点もありますが、これについては後で説明します。
場合によっては、テーブル間の関係を表現するために自然キーを使用すると問題が発生する可能性があります。たとえば、自然キーがであるPERSONテーブルがあるとします{LAST_NAME, FIRST_NAME, SSN}
。Proposer、Reviewer、Approver、およびAuthorizerへの参照を格納する必要がある他のテーブルGRANT_PROPOSALがある場合はどうなりますか。この情報を表現するには、12列が必要です。また、どの列がどの種類の個人に属しているかを識別するために、ある種の命名規則を考え出す必要があります。しかし、PERSONテーブルが自然キーに6、8、または24列を必要とした場合はどうなるでしょうか。これは急速に管理不能になります。代理キーは、キーのセマンティクス(意味)を識別子としての使用から切り離すことにより、このような問題を解決します。
質問で説明した例も見てみましょう。
状態の2文字の省略形を、そのテーブルの主キーとして使用する必要があります。
表面的には、省略形フィールドが適切な主キーの要件を満たしているように見えます。比較的短く、外部キーとして伝播しやすく、安定しているように見えます。残念ながら、あなたは一連の略語を管理していません...郵便局は管理しています。そして、ここに興味深い事実があります。1973年、USPSは、カナダのニューブランズウィックとの混乱を最小限に抑えるために、ネブラスカの略語をNBからNEに変更しました。この話の教訓は、自然キーはデータベースの制御外にあることが多く、時間の経過とともに変化する可能性があるということです。できないと思っても。この問題は、人や製品などのより複雑なデータではさらに顕著になります。ビジネスが進化するにつれて、そのようなエンティティを一意にするものの定義が変わる可能性があります。そして、これはデータモデラーやアプリケーション開発者にとって重大な問題を引き起こす可能性があります。
先ほど、主キーがキーのポリモーフィズムをサポートできることを説明しました。どういう意味ですか?さて、ポリモーフィズムとは、あるタイプAが、別のタイプBのように見え、そのように使用される能力のことです。データベースでは、この概念は、さまざまなクラスのエンティティのキーを1つのテーブルに結合する機能を指します。例を見てみましょう。どのエンティティがどのユーザーによってどの日付に変更されたかを識別する監査証跡をシステムに持たせたいと想像してみてください。次のフィールドを使用してテーブルを作成すると便利です{ENTITY_ID, USER_ID, EDIT_DATE}
。残念ながら、自然キーを使用すると、エンティティごとにキーが異なります。したがって、別のリンクテーブルを作成する必要がありますエンティティの種類ごとに...そして、さまざまな種類のエンティティとそれらのキーがどのように形成されるかを理解する方法でアプリケーションを構築します。
誤解しないでください。私は、代理キーを常に使用する必要があると主張しているわけではありません。現実の世界では、決して、これまで、そして常に採用するのは危険な立場です。代理キーの最大の欠点の1つは、多くの「意味のない」数値で構成される外部キーを持つテーブルが作成される可能性があることです。これにより、全体像を取得するために他のテーブルからレコードを結合または検索する必要があるため、レコードの意味を解釈するのが面倒になる可能性があります。また、サーバー間で一意の増分番号を割り当てることが常に可能であるとは限らないため、分散データベースの展開がより複雑になる可能性があります(ただし、OracleやSQLServerなどの最新のデータベースはシーケンスレプリケーションによってこれを軽減します)。