次の例をご覧ください。
- これが適切な場合
- これが適切でない場合
データベースの選択が上記の例に違いをもたらす時期はありますか?
次の例をご覧ください。
データベースの選択が上記の例に違いをもたらす時期はありますか?
これは実際には、常に自動インクリメント番号またはGUIDのいずれかであるため、単一の列であるサロゲートキーと、真に一意であるために複数の情報を必要とすることが多い自然キーに関する質問のようです。1列しかない自然キーを持つことができれば、とにかく要点は明らかに議論の余地があります。
どちらか一方だけを使用することを主張する人もいます。本番データベースでの作業に十分な時間を費やすと、コンテキストに依存しないベストプラクティスがないことがわかります。
これらの回答の一部はSQLServerの用語を使用していますが、この概念は通常、すべてのDBMS製品に適用できます。
クラスター化インデックス。 クラスター化インデックスは、データベースが単に追加できる場合に常に最高のパフォーマンスを発揮します。それ以外の場合、DBはページ分割を行う必要があります。これは、キーがシーケンシャルである場合、つまり自動インクリメントシーケンスまたはシーケンシャルGUIDの場合にのみ適用されることに注意してください。任意のGUIDは、パフォーマンスが大幅に低下する可能性があります。
関係。キーが3、4、5列の長さで、文字タイプやその他の非コンパクトデータを含む場合、他の20のテーブルでこのキーとの外部キー関係を作成する必要があると、膨大なスペースが無駄になり、パフォーマンスが低下します。
独自性。真の自然キーがない場合があります。たぶん、あなたのテーブルはある種のログであり、同じイベントを同時に2つ取得する可能性があります。または、実際のキーは、行がすでに挿入された後でのみ決定できるマテリアライズドパスのようなものである可能性があります。いずれにせよ、クラスター化インデックスや主キーを常に一意にする必要があるため、他に本当に一意の情報がない場合は、代理キーを使用するしかありません。
互換性。 ほとんどの人はこれに対処する必要はありませんが、自然キーにhierarchyid
のようなものが含まれている場合、一部のシステムはそれを読み取ることさえできない可能性があります。この場合も、これらのアプリケーションで使用するための単純な自動生成された代理キーを作成する必要があります。自然キーに「奇妙な」データがない場合でも、この問題はすぐに解消されますが、一部のDBライブラリでは複数列の主キーの処理に多くの問題が発生します。
ストレージ。データベースを扱う多くの人々は、この要因を気にする必要があるほど大きなデータベースを扱うことは決してありません。ただし、テーブルに数十億または数兆の行がある場合は、このテーブルに可能な限り最小限のデータを保持する必要があります。
レプリケーション。はい、GUIDまたはシーケンシャルGUIDを使用できます。ただし、GUIDには独自のトレードオフがあり、何らかの理由でGUIDを使用できない、または使用したくない場合は、本質的にグローバルに一意であるため、複数列の自然キーがレプリケーションシナリオに適しています。つまり、一意にするために特別なアルゴリズムは必要ありません。定義上、一意です。これにより、分散アーキテクチャについての推論が非常に簡単になります。
パフォーマンスの挿入/更新。代理キーは無料ではありません。一意で頻繁にクエリが実行される列のセットがあるため、これらの列にカバーインデックスを作成する必要がある場合。インデックスはテーブルとほぼ同じ大きさになり、スペースを浪費し、変更を加えるたびに2番目のインデックスを更新する必要があります。テーブルにインデックス(クラスター化インデックス)を1つだけ持つことが可能な場合は、それを行う必要があります。
それがすぐに頭に浮かぶことです。急に何か覚えたら更新します。
ほとんどの場合、主キーが必要なので、既存の2つの列を主キーとして選択するか、新しい自動インクリメントPKを作成して、代わりに2つの列に通常の一意性制約を設定するかを選択すると思います。
2列の主キーが必要な場合:
自動インクリメントの主キーが必要な場合:
ほとんどの場合、(少なくともアプリケーション開発者の観点からは)主キーを自動生成キーにし、複数の列にUNIQUE制約とインデックスを作成する方が良いと思います。
DBAは複数列の主キーで常に十分であると考えていたため、頭痛を引き起こすいくつかの状況に遭遇しました。将来の要件の変更により、これが正しくないことが判明しました。
いくつかの例...
適切な:
不適切:
OLAPシステムのディメンションテーブルの場合-ファクトテーブルをできるだけ小さく(そして高速に)するために、ディメンションキーをできるだけ小さくする必要があります。
組み合わせがユニークかどうかわからないときのために。確かにこれはかなり厄介な例ですが、「Person」テーブルは複数列のPKには適していません。
複数列のインデックスとキーを使用すると、アプリケーションのパフォーマンスが大幅に向上することがわかりました。これにより、最も一般的なクエリでインデックスを作成でき、select句全体がインデックスに含まれる可能性があるため、メインテーブルにもアクセスできませんでした。ただし、アプリとデータセットによって異なります。
適切な場合の1つの例は、異なるテーブルを接続する外部キーフィールドを持つリンクテーブルがある場合です。
一般に、可能であれば、既存の識別フィールドを主キーとして使用することをお勧めします。自然なIDフィールドがなく、一意のPKを取得するために多くのフィールドを組み合わせる必要がある場合は、自動番号を使用することをお勧めします。2つ以上のフィールドを持つ主キーは乱雑になる可能性があります。
複合自然キーが直感的に理解できる場合があります。たとえば、会社のテーブル(PKはComapnyId)があり、その会社の詳細が列に表示されているとします。また、会社の歴史を通して会社のCEO名を保存する必要があります。自然な不変は、1つの会社が一度に1人のCEOしか持つことができないということです。次に、CompanyId(CompanyテーブルのCompanyIdへのFK)+FromDateの複合PKを使用してCompanyCeoテーブルを作成するのは直感的です。そのテーブルの他の列は、ToDateとCeoNameである可能性があります。このようにして、特定の日に1人のCEOだけが開始できることを保証できます。