データベース設計で外部キーは本当に必要ですか?


109

私の知る限り、外部キー(FK)は、プログラマーがデータを正しい方法で操作するのを支援するために使用されます。プログラマが既にこれを正しい方法で行っているとしたら、外部キーの概念が本当に必要なのでしょうか。

外部キーの他の用途はありますか?ここで何か不足していますか?


2
これはこの辺りでよく出てきます。私はジョエル・スポルスキーを非難します:-)。ここには多くの良い答えがあります。:むしろ再入力鉱山よりも、私はあなたにリンクあげるstackoverflow.com/questions/83147/whats-wrong-with-foreign-keys
SquareCog

70
「プログラマーがすでにこれを正しい方法で行っているとしましょう」-そのようなシナリオを想像することすらできません。
再帰的

11
「Foreign Key」はアイデアではなく、テクノロジーです。これは関係ルールです。あなたの質問は本当にあなたがあなたのコードでルールを強制しようとするべきか、それともデータベースがあなたを助けるようにするべきかについてです。同時実行が関係する場合、コードで認識できない可能性があるデータベース内で発生するすべてのことを認識しているため、データベースエンジンでルールを適用することをお勧めします。
Triynko、2009

5
@lubos&cdeszaq。実際、これはリレーショナルルールです...コッドの「Twleveの戒め」の「ルール10のサブセットです...わかりやすく説明していた通りです。このルールは、とりわけ、外部キー制約によって実装されます。したがって、はい、外部キーの概念は「a」の関係ルールです。
Triynko、2010

1
@lubos:明確にするために、特定の機能を使用するかどうかについて話しているが、完全で完全に機能するRDBMSを使用するためにその機能の存在が必要かどうかについて話している。参照制約は、それらを使用することを選択した場合、RDBMS内で(アプリケーションではなく)強制する必要があるものであるため、そこにあるべき機能であり、その意味では、リレーショナルモデルの要件です。完全なRDBMSを開発します。
Triynko

回答:


102

外部キーは、データレベルで参照整合性を適用するのに役立ちます。また、通常はデフォルトでインデックスが作成されるため、パフォーマンスも向上します。


52
インデックスを作成する必要がある場合、これがFKの主な理由ではありません。(実際には、特定の状況(たとえば、選択よりも挿入数が多い)でFKの維持が遅くなることがあります。)
Robert

7
これは恐ろしい回答です。FKは一般的にオーバーヘッドを追加してパフォーマンスを向上させることはできません。
アジャイルジェダイ

SQL-Serverでは、レフェリーとリファラーのどちらにもデフォルトでインデックスが付けられていません。 sqlskills.com/blogs/kimberly/...
user420667

1
オラクルでもありません。(FK列に)インデックスを自分で作成する必要があります。
リトルフット、2018

58

外部キーは、プログラマーがなどを使用してより少ないコードを書くのにも役立ちますON DELETE CASCADE。つまり、1つのテーブルにユーザーが含まれ、別のテーブルに注文などが含まれている場合、ユーザーを削除すると、そのユーザーを指すすべての注文が自動的に削除される可能性があります。


3
@Greg Hewgillこれは潜在的に多くの問題を引き起こす可能性があります。多くの場合、ユーザーを削除するときにユーザーが作成した注文を保持する必要があるため、DELETE CASCADEのような考え方には非常に注意する必要があります。
Kibbee 2008

8
ただし、これはおそらくビジネスロジック層で処理する必要があります。関連する子レコードを保持するかどうかを決定することは、値が外部キーの関係に違反しないことを保証することとはまったく同じではありません。
Codewerks 2008年

5
もう1つの問題は監査です。監査がデータベースレベルで行われていない場合、更新または削除をカスケードすると監査証跡が無効になります。
si618 2009

@Codewerks:ビジネスロジックをDBに含めることができます。
ファンティウス

44

外部キーなしでデータベースを設計することは想像できません。それらがなければ、最終的には間違いを犯し、データの整合性を破壊することになります。

彼らは必要ありませ厳密にが、メリットは非常に大きくなります。

私はFogBugzがデータベースに外部キー制約を持たないことをかなり確信しています。Fog Creek Softwareチームがコードをどのように構成して、矛盾が発生しないことを保証するかについて興味があります。


43
Joel:「これまでのところ問題はありませんでした。」これまでのところ、私は街灯柱に運転したことがありません。しかし、私はまだシートベルトを着用することをお勧めします;-)
トニー・アンドリュース

2
あなたは問題を決して見たことがないかもしれませんが、それがそこにあるかもしれません...ほとんどのデータベースは、idXXXxのようなixXXXとまったく同じ規則を使用しています
FerranB

1
@ジョエル:ルールの施行の代わりに命名規則?タイプしている間は、タイプを廃止することもできます。
jcollum 2009

8
@エリック:あなたは、ここでソフトウェア開発のある種のアバターとしてFog Creekを掲げています。「ニューヨーク市の会社のdbに外部キーがない...」と言ったら、みんな「あれ?」と言うでしょう。
jcollum 2009

3
エリック:FogBugzは外部キーの命名規則を使用します。たとえば、ixBugは、Bugテーブルの主キーへのインデックスであると理解されています。これまでのところ問題はありません。-Joel Spolsky
Sam Saffron

40

FK制約のないデータベーススキーマは、シートベルトなしの運転に似ています。

ある日、あなたはそれを後悔するでしょう。設計の基礎とデータの整合性に少しの余分な時間を費やさないことは、後で頭痛を確実にする確実な方法です。

ずさんなコードをアプリケーションで受け入れますか?メンバーオブジェクトに直接アクセスし、データ構造を直接変更しました。

なぜこれが難しくなり、現代の言語では受け入れられなくなったと思いますか?


2
+1は、カプセル化とFK / PKの関係の良い類似点です。
jcollum 2009

21

はい。

  1. 彼らはあなたを正直に保ちます
  2. 彼らは新しい開発者を正直に保つ
  3. できるよ ON DELETE CASCADE
  4. それらは、テーブル間のリンクを自己説明する素晴らしい図を生成するのに役立ちます

1
正直ってどういう意味?
dspacejs

私は推測する概念に正直です。それはあなたが迅速で不完全なプログラミングをすることによってデータで不正行為をすることを防ぎます。
オレストビロン2017年

13

プログラマが実際にこれをすでに正しい方法で行っていると仮定します

そのような仮定をすることは、私には非常に悪い考えのようです。一般的に、ソフトウェアは驚くほどバグがあります。

そして、それが本当にポイントです。開発者は物事を正しく行うことができないため、データベースに不正なデータを入れないようにすることは良いことです。

理想的な世界では、自然結合は列名を一致させるのではなく、関係(つまり、FK制約)を使用します。これにより、FKがさらに便利になります。


2
良い点は、 "ON [Relationship]"または他のキーワードを使用して2つのテーブルを結合し、どの列が関係しているかをデータベースが把握できるようにすることです。かなりリーズナブルに思えます。
jcollum 2009

13

個人的には、テーブル間の関係を形式化するため、外部キーを支持しています。あなたの質問がプログラマーが参照整合性に違反するデータを導入していないことを前提としていることを理解していますが、最善の意図にもかかわらず、データ参照整合性に違反する事例が多すぎます!

事前に外部キーの制約(宣言的参照整合性またはDRIとも呼ばれます)には、トリガーを使用してこれらの関係を実装するために多くの時間が費やされました。宣言的な制約によって関係を形式化できるという事実は非常に強力です。

@John-他のデータベースは外部キーのインデックスを自動的に作成しますが、SQL Serverは作成しません。SQL Serverでは、外部キー関係は制約にすぎません。外部キーのインデックスを個別に定義する必要があります(これは有益な場合があります)。

編集:追加したいのですが、IMO、ON DELETEまたはON UPDATE CASCADEをサポートするための外部キーの使用は必ずしも良いことではありません。実際には、削除のカスケードはデータの関係に基づいて慎重に検討する必要があることを発見しました。たとえば、これが問題ない自然な親子があるか、関連するテーブルがルックアップ値のセットであるかなどです。カスケード更新を使用すると、1つのテーブルの主キーを変更できるようになります。その場合、テーブルの主キーが変更されるべきではないという点で、一般的な哲学的な不一致があります。キーは本質的に一定でなければなりません。


9

外部キーがなければ、異なるテーブルの2つのレコードが関連しているとどうやって判断できますか?

あなたが参照しているのは参照整合性であり、既存の親レコードがないと子レコードを作成できないなどです。これらはしばしば外部キー制約と呼ばれますが、外部キーの存在と混同しないでくださいそもそも。


8

外部キーがないことにはメリットがありますか?安っぽいデータベースを使用しているのでない限り、FKの設定はそれほど難しくありません。それでは、なぜそれらを回避する方針があるのでしょうか。列が別の列を参照するという命名規則を持つことは1つのことです。データベースが実際にその関係を検証していることを知ることは別のことです。


8

データベースによって強制される外部キー制約について話していると思います。おそらくすでに外部キーを使用していますが、データベースについてそれを知らせていないだけです。

プログラマが既にこれを正しい方法で行っているとしたら、外部キーの概念が本当に必要なのでしょうか。

理論的には違います。ただし、バグのないソフトウェアはありません。

通常、アプリケーションコードのバグはそれほど危険ではありません。バグを特定して修正すると、アプリケーションは再びスムーズに実行されます。しかし、バグが原因で破損したデータがデータベースに入力されると、それで立ち往生してしまいます。データベース内の破損したデータから回復するのは非常に困難です。

FogBugzの微妙なバグにより、破損した外部キ​​ーがデータベースに書き込まれる可能性があるかどうかを検討してください。バグを修正し、バグ修正リリースで顧客にすばやく修正をプッシュするのは簡単かもしれません。しかし、数十のデータベースの破損したデータをどのように修正すればよいですか?正しい外部キーの整合性に関する仮定がもう成り立たないため、コードが突然壊れる可能性があります。

Webアプリケーションでは、通常、データベースと通信するプログラムは1つだけなので、バグがデータを破壊する可能性のある場所は1つだけです。エンタープライズアプリケーションでは、同じデータベースと対話する複数の独立したアプリケーションが存在する場合があります(データベースシェルで直接作業している人は言うまでもありません)。すべてのアプリケーションが、常に、そして永遠に、バグのない同じ仮定に従うことを確認する方法はありません。

制約がデータベースでエンコードされている場合、バグで発生する可能性のある最悪の事態は、SQL制約が満たされていないという醜いエラーメッセージがユーザーに表示されることです。これはたくさんです、破損したデータをエンタープライズデータベースに入れて、すべてのアプリケーションを破壊したり、あらゆる種類の誤った、または誤解を招く出力をもたらすよりも好ましい方法です。

また、外部キー制約はデフォルトでインデックスが付けられるため、パフォーマンスも向上します。外部キー制約を使用しない理由は何も考えられません。


7

FKは非常に重要であり、eBayない限り、常にスキーマに存在する必要があります。


2
そのリンクは実際には非常に魅力的です...私は本当に詳細を知りたいと思います、そして今私はebayを使うのが少し怖いです。他の人の場合:4番目の質問をクリックして、db構造について彼が何を言っているかを確認してください。ただし、インタビュー全体は一見の価値があります。また...unibrow
gloomy.penguin 2013

6

私が思うに、いくつかの単一の事をある時点での、有効な関係を確実にする責任があるに違いないと。

たとえば、Ruby on Railsは外部キーを使用しませんが、すべての関係自体を検証します。Ruby on Railsアプリケーションからデータベースにアクセスするだけの場合は、これで問題ありません。

ただし、データベースに書き込むクライアントが他にある場合は、外部キーがないと、独自の検証を実装する必要があります。次に、異なる可能性が最も高い検証コードのコピーが2つあります。これは、どのプログラマーもそれが主要な罪であることを伝えることができるはずです。

その時点で、外部キーは責任を1つのポイントに再び移動できるため、本当に必要です。


2
タマネギのようなものです。FKは最後の防御層です。埋め込まれたローカルデータベースでない限り、参照整合性を実行しようとするアプリは常に悪い考えです。
Fabricio Araujo 2013年

5

外部キーを使用すると、以前にデータベースを見たことがない人でも、テーブル間の関係を判別できます。

今はすべてうまくいくかもしれませんが、プログラマが去って他の誰かが引き継ぐ必要があるときに何が起こるか考えてください。

外部キーを使用すると、何千行ものコードを調べなくてもデータベース構造を理解できます。


5

私の知る限り、外部キーは、プログラマーがデータを正しい方法で操作するのを助けるために使用されます。

FKにより、DBAは、プログラマーが失敗したときにユーザーの手ごたえからデータの整合性を保護し、場合によってはプログラマーの手ごたえから保護することができます。

プログラマが既にこれを正しい方法で行っているとしたら、外部キーの概念が本当に必要なのでしょうか。

プログラマーは人間であり、間違いです。FKは宣言的であるため、失敗することが難しくなります。

外部キーの他の用途はありますか?ここで何か不足していますか?

これが作成された理由ではありませんが、FKは、作図ツールとクエリビルダーに強力で信頼性の高いヒントを提供します。これは、強力で信頼性の高いヒントを切実に必要とするエンドユーザーに渡されます。


これは素晴らしい答えです。
Dan Lugg、2013年

4

シートベルトが厳密に必要ではないので、それらは厳密に必要ではありません。しかし、データベースをめちゃくちゃにする愚かなことからあなたを救うことができます。

FK制約エラーをデバッグする方が、アプリケーションを破壊した削除を再構築する必要があるよりもはるかに優れています。


4

アプリケーションがデータベース内のデータを操作できる唯一の方法ではないため、これらは重要です。アプリケーションは参照整合性を必要に応じて正直に処理できますが、必要なことは、データベースレベルで挿入、削除、または更新コマンドを実行するための適切な権限を持つ1つのbozoだけであり、すべてのアプリケーションの参照整合性の適用はバイパスされます。FK制約をデータベースレベルで配置すると、このbozoがコマンドを発行する前にFK制約を無効にすることを選択しないと、FK制約により、挿入/更新/削除ステートメントが失敗し、参照整合性違反が発生します。


3

コスト/メリットの観点から考えます... MySQLでは、制約の追加はDDLの 1行の追加ですです。それはほんの一握りのキーワードと数秒の思考です。それは私の意見では唯一の「コスト」です...

ツールは外部キーを愛します。外部キーは、ビジネスロジックまたは機能に影響を与えないために気付かれずに蓄積される不良データ(つまり、孤立した行)を防ぎます。また、スキーマに不慣れな開発者が、関係が欠落していることに気付かずに作業のチャンク全体を実装することもできません。おそらく、現在のアプリケーションの範囲内ではすべてが素晴らしいですが、何かを見落とし、いつか予期しない何かが追加された場合(空想的なレポートと考えてください)、最初から蓄積されている不良データを手動でクリーンアップする必要がある場合があります。データベースがチェックを強制しないスキーマの。

物事をまとめるときにすでに頭の中にあるものを成文化するのにかかる少しの時間は、あなたや他の誰かが、数ヶ月または数年の悲しみをたくさん救うことができます。

質問:

外部キーの他の用途はありますか?ここで何か不足していますか?

少しロードされています。「外部キー」の代わりにコメント、インデント、または変数名を挿入します...問題の問題を完全に理解している場合は、「使用しない」ことになります。


2

エントロピーの削減。データベースで無秩序なシナリオが発生する可能性を減らします。すべての可能性を考慮しているので、私たちは苦労しています。したがって、私の意見では、エントロピーの低減は、あらゆるシステムのメンテナンスの鍵となります。

たとえば、仮定を立てるとき:各注文には、何かによって仮定が強制されるべきであるという顧客がいます。データベースでは、「何か」は外部キーです。

これは開発速度のトレードオフの価値があると思います。確かに、それらをオフにしておくとより速くコードを作成できます。これがおそらく一部の人々がそれらを使用しない理由です。個人的には、NHibernateといくつかの操作を実行すると怒るいくつかの外部キー制約で数時間を殺しました。しかし、私は問題が何であるかを知っているので、それほど問題ではありません。私は通常のツールを使用しており、これを回避するのに役立つリソースがあります。

代替策は、外部キーが設定されておらず、データが不整合になるバグがシステムに侵入することを許可することです(十分な時間が与えられれば、システムに侵入します)。次に、異常なバグレポートを取得し、調査して「OH」にします。データベースが台無しになっています。それを修正するには、どれくらい時間がかかりますか?


1

外部キーを制約と見なすことができます。

  • データの整合性を維持するのに役立ちます
  • データが互いにどのように関連しているかを示します(これはビジネスロジックとルールの適用に役立ちます)
  • 正しく使用すると、テーブルからデータをフェッチする効率を上げることができます。

1

現在、外部キーは使用していません。そして、大部分は後悔していません。

とはいえ、いくつかの理由により、近い将来、それらの使用がさらに増えると思われます。両方とも、同様の理由からです。

  1. 作図。正しく使用されている外部キー関係がある場合は、データベースの図を作成する方がはるかに簡単です。

  2. ツールのサポート。適切な外部キー関係がある場合は、LINQ to SQLに使用できるVisual Studio 2008を使用してデータモデルを構築する方がはるかに簡単です。

ですから、私のポイントは、多くの手動のSQL作業(クエリの構築、クエリの実行、何とか)を実行している場合、外部キーは必ずしも必須ではないことを発見したということです。ただし、ツールの使用を開始すると、ツールはより便利になります。


1
それらを使用しないシステムで作業しています。そして、私は定期的にそれを後悔しています。適切な制約によって妨げられたであろう、無意味なデータの数を数えることができるインスタンスがさらに増えました。
再帰

私たちの現在のプロジェクトで外部キーを6か月近く使用してきたので、このコメントに完全に同意します。
ジョンクリステンセン

1

外部キー制約(および実際の制約一般)の最も良い点は、クエリを作成するときにそれらに依存できることです。「true」を保持するデータモデルに依存できない場合、多くのクエリはさらに複雑になる可能性があります。

コードでは、通常、どこかで例外がスローされますが、SQLでは、通常、「間違った」答えが返されます。

理論的には、SQL Serverはクエリプランの一部として制約を使用できますが、パーティション分割のチェック制約を除いて、実際にそれを目にしたことはありません。


一意性の制約は、オプティマイザが結合メカニズムを選択するときに使用するカーディナリティが高いことを示します。
Peter Wone、2009

1

外部キーは、私が取り組んでいるプロジェクト(ビジネスアプリケーションおよびソーシャルネットワーキングウェブサイト)で宣言されていなかった(FOREIGN KEY REFERENCESテーブル(列))。

しかし、常に外部キーである列の命名規則のようなものがありました。

それはデータベースの正規化のようなものです-あなたはあなたが何をしているか、そしてその結果(主にパフォーマンス)が何であるかを知る必要があります。

外部キーの利点(データ整合性、外部キーカラムのインデックス、データベーススキーマを認識するツール)は知っていますが、一般的なルールとして外部キーを使用することも怖いです。

また、さまざまなデータベースエンジンが異なる方法で外部キーを提供する可能性があり、移行中に微妙なバグにつながる可能性があります。

ON DELETE CASCADEを使用して、削除されたクライアントのすべての注文と請求書を削除することは、見栄えは良いが設計が間違っているデータベーススキーマの完璧な例です。


0

はい。ON DELETE [RESTRICT | CASCADE]は、開発者がデータを取り残さないようにし、データをクリーンに保ちます。私は最近、外部キーなどのデータベースの制約に重点を置かなかったRails開発者のチームに参加しました。

幸いなことに、私はこれらを見つけました:http : //www.redhillonrails.org/foreign_key_associations.html-Ruby on RailsプラグインのRedHillは、設定スタイルの規約を使用して外部キーを生成しますproduct_idを使用した移行では、productsテーブルのidへの外部キーが作成されます。

トランザクションにラップされた移行を含む、RedHillの他の優れたプラグインをチェックしてください。


0

Entity Frameworkやその他のORMなどのデータアクセスコードを生成する場合は、外部キーなしで階層モデルを生成できなくなります。

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