外部キーの何が問題になっていますか?


259

私は聞いた覚えジョエル・スポルスキの中で言及をポッドキャスト014(私は記憶が正しければ)彼はやっと今までに外部キーを使用したいということ。しかし、私にとっては、データベース全体で重複やそれに続くデータの整合性の問題を回避するために非常に重要なようです。

理由については、確かな理由がありますか(スタックオーバーフローの原則に沿った議論を避けるため)。

編集: 「外部キーを作成する理由がまだないので、実際に設定するのはこれが最初の理由かもしれません。」


9
JoelがFKを使用していないとは思いません。FKをデータベースに強制させないだけです。論理的には、まだFKです。
ダレントーマス

6
彼は彼が外部キーを使用しないと言います、しかし私が彼が意味することは彼が外部キー制約を使用しないことであるとダーレンに同意します。制約を追加するかどうかに関係なく、値が別のテーブルの主キーまたは一意キーから取得されることになっている1つのテーブルの列は、外部キーです。
トニーアンドリュース

22
...一般に、制約を追加しないのは愚かです。アプリケーションコードにバグがある場合や、データの「修正」を行っている舞台裏で作業している場合でも、常に整合性が保証されます。
トニーアンドリュース

2
+1トニーのコメント。機能とそこにある外部キーの論理的概念の間には、あまりにも多くの混乱があります。
JohnFx

4
@DanMan、あなたが印象をどこで得たのかわからないと思います。私は実際に上記のように言っています。「一般に、制約を追加しないのはばかげています。常に整合性を保証します」
Tony Andrews、

回答:


352

外部キーを使用する理由:

  • 孤立した行を取得しません
  • 「削除時のカスケード」動作を実現し、テーブルを自動的にクリーンアップできます
  • データベース内のテーブル間の関係を知ることにより、オプティマイザは結合のカーディナリティをより正確に見積もることができるため、クエリを最も効率的に実行するための計画を立てるのに役立ちます。
  • FKは、データベースで収集する最も重要な統計についてかなり大きなヒントを与え、それにより、パフォーマンスが向上します。
  • それらはあらゆる種類の自動生成サポートを有効にします-ORMはそれ自体を生成することができ、視覚化ツールはあなたのために素晴らしいスキーマレイアウトを作成することができます。
  • そうでない場合は暗黙の関係が明示的に文書化されているため、プロジェクトの初心者は、より迅速に物事の流れに入ります

外部キーを使用しない理由:

  • FKの一貫性をチェックする必要があるため、すべてのCRUD操作でDBの作業を追加します。解約が多い場合、これは大きなコストになる可能性があります
  • リレーションシップを適用することにより、FKは物事を追加/削除する必要がある順序を指定します。これにより、DBが必要なことを拒否する可能性があります。(そのような場合に許可されるのは、孤立行を作成することですが、通常はそれは良いことではありません)。これは、大規模なバッチ更新を実行していて、2つのテーブルが一貫した状態を作成しながら、1つのテーブルを次々にロードする場合に特に痛みを伴います(ただし、2番目のロードが失敗し、データベースに不整合がありますか?)。
  • データがダーティになることが事前にわかっている場合があり、それを受け入れ、DBがそれを受け入れたい場合があります。
  • あなたはただ怠惰です:-)

ほとんどの確立されたデータベースは、強制されておらず、単なるメタデータである外部キーを指定する方法を提供していると思います(確信はありません!)。非施行はFKを使用しないすべての理由を一掃するので、2番目のセクションのいずれかの理由が当てはまる場合は、おそらくそのルートに進む必要があります。


12
良いリスト!DBMはCRUDの「R」部分の整合性をチェックしないため、その部分は除外します。また、アプリでDBMSが行うのと同じことを行うため、おそらくウォッシュです。CRDの前に親IDが有効であることを確認し、DBMが行うよりも実際には遅いことを確認します。
Matt Rogish

6
子供を挿入しているときに誰かが親を削除するとどうなりますか?現時点で「コメントの追加」を送信すると、すでに回答を削除している場合、このコメントは孤立しています。FKはそれを防げたでしょう。また、parentIDを好きなように変更することもできます。誰かが確認する必要があります。:)
Matt Rogish 2008

7
正確に言うと、複数の同時クライアントに直面してもトランザクション性を保証できるのはDBだけなので、これはDBの仕事です。
SquareCog 2008

3
1優秀な答えは- FK制約を使用しない第2の理由は、実際のように聞こえる「それは難しい一貫破る可能」と考えることができ良いものを!
ビルカーウィン

9
私の意見では、FARを使用することの利点は、それらを使用しないことの利点よりも重要です。
Nick Bedford

80

これは育成の問題です。教育的または専門的なキャリアのどこかにデータベースの養育やケアに時間を費やした場合(またはそうした有能な人々と緊密に連携した場合)、エンティティおよび関係の基本的な信条は思考プロセスに深く根付いています。それらの初歩的なものの中には、データベースでキーを指定する方法/時期/理由(プライマリ、外部、およびおそらく代替)があります。それは第二の性質です。

ただし、過去にRDBMS関連の取り組みでこれほど徹底的または前向きな経験をしたことがない場合は、そのような情報に触れたことはないでしょう。あるいは、あなたの過去には、反データベースのような環境への没入が含まれています(たとえば、「これらのDBAは馬鹿です-私たちが選択したjava / c#コードはほとんどありません」)。この場合、あなたは激しく反対するかもしれません。あなたがただ聞くだけなら、FK(とFKが意味する可能性のある制約)は本当に重要であるとあなたに言っているいくつかのdweebの難解なせせらぎに。

ほとんどの人は子供であるときに、歯を磨くことが重要であると教えられました。あなたはそれなしでうまくいくことができますか?確かに、しかしどこかで、毎食後にブラシをかけた場合よりも歯の数が少なくなります。ママとパパがデータベース設計と口腔衛生をカバーするのに十分な責任があるとしたら、私たちはこの会話をすることはないでしょう。:-)


61
私は蒸留された「外国の鍵は歯を磨くようなものです。先に進んでください、それなしでやってください、しかしあなたが笑うときは注意してください」
Mark Sowul

5
私は個人的に、RDBMSの原則は、口腔衛生の原則よりもはるかに単純で、はるかに明確であると感じています
Ali Gangji

10年後、私はこのデータベースの設計を息子/娘と話し合うことになるでしょう。息子/娘がデータベースの問題のために次のウォール街のクラッシュの原因となることはありません。
VarunAgw 2018

52

私はあなたがそれを回避することができる多くのアプリケーションがあると確信していますが、それは最良の考えではありません。アプリケーションを信頼してデータベースを適切に管理できるとは限りません。データベースを率直に管理することは、アプリケーションにとってあまり重要ではありません。

リレーショナルデータベースを使用している場合は、いくつかの関係を定義する必要があります。残念ながら、この態度(外部キーは必要ありません)は、データの整合性などのばかげたものに煩わされたくない(ただし、企業には専用のデータベース開発者がいないため必要になる)多くのアプリケーション開発者に採用されているようです。通常、これらのタイプでまとめられたデータベースでは、主キーだけで幸運です;)


26
データベースにFKがない人は本当にいません。持っていない人と最後に作業したとき、彼は「いいえ、アプリケーションでそれを強制します」と言った。例外として、すべての顧客データベースの調査を行ったところ、それらのほとんどに孤児がいることがわかりました
ErikE

1
通常はそうです。(ユーザーがランタイム例外を気にしない限り)データベースでのみ適用することで問題は解決できると思いますが、両方を実行するのが本当に唯一の方法です。
AlexCuse

トランスクリプトのすべて/ Atwoodの応答 "Atwood:...インデックスに設定した外部キ​​ーに基づいて、それらはそれを理解します。データベースを適切に設定した...」
MemeDeveloper 2013年

4
データベースが呼び出されないリレーショナルための関係テーブル間の(データベースのあらゆる種類のエンティティ間の関係のいくつかの種類を持っている!)が、テーブルのために自身がある関係数学の面では、。Wikipediaを参照してください。
Massimiliano Kraus

41

外部キーは、リレーショナルデータベースモデルに不可欠です。


54
モデル、はい。実装は必須ではありませんが、おそらく便利です。
dkretz 2009年

4
申し訳ありませんが、アプリ開発者がオブジェクトデータベース管理システム(別名NoSQLデータベース!)をより広く使用しない主な理由は、RDBMSへの投資によるものです。ほとんどの場合、データベース(データベース管理システムではない)は、多くの場合分散キャッシュを含む中間層オブジェクトモデルです。これは、削除のカスケード、所有権、変更の同期がとにかく発生しなければならない場所です。RDBMSは、主にこのオブジェクトモデルの永続化に使用され、通常、骨の折れる実用的に価値のないORMの実行後に使用されます。ほとんどの場合、リレーションモデルは必要ありません。
Sentinel

2
いいえ、外部キーは「リレーショナル」を示すことを強制されていません
シルバームーン

これは実際にはあまり説明しません。
Nae、

29

いつも使っていますが、それから金融システムのデータベースを作っています。データベースはアプリケーションの重要な部分です。財務データベースのデータが完全に正確でない場合は、コード/フロントエンド設計にどれほどの労力を費やしてもかまいません。あなたはただあなたの時間を無駄にしています。

複数のシステムが一般にデータベースと直接やり取りする必要があるという事実もあります-データを読み取るだけのその他のシステム(Crystal Reports)からデータを挿入するシステム(必ずしも私が設計したAPIを使用する必要はありません)は、 VBScriptを発見したばかりでSQLボックスのSAパスワードを持っている頭の悪いマネージャー)さてさようならデータベースは、データベースがおそらく可能なほど馬鹿に耐えられない場合です。

データが重要な場合は、はい。外部キーを使用し、一連のストアドプロシージャを作成してデータとやり取りし、最も堅牢なDBを作成します。データが重要ではない場合、データベースを作成するのはなぜですか。


2
素晴らしい洞察力。データは、実際に使用されるすべてのアプリケーションにとってこれが重要であると私は主張します。唯一異なる点は、破損したデータの影響です。彼らはあなたの種類のアプリにとって高いです...
ジェイ・ゴッセ

20

更新:私は常に外部キーを使用しています。「彼らの複雑なテスト」に対する私の答えは、「データベースをまったく必要としないように単体テストを作成することです。データベースを使用するすべてのテストは、それを適切に使用する必要があり、外部キーを含みます。設定が面倒な場合は、セットアップを簡単にする方法を見つけてください。」


外部キーは自動テストを複雑にします

外部キーを使用しているとします。「金融口座を更新すると、取引の記録が保存されるはずです」という自動テストを書いています。このテストでは、あなただけの二つのテーブルに関係している:accountstransactions

ただし、accountsへの外部キーがありcontracts、へcontractsのfkがありclients、へclientsのfkがありcities、へcitiesのfkがありstatesます。

これで、データベースは、テストに関連しない4つのテーブルにデータを設定しないと、テストを実行できなくなります

これには少なくとも2つの考えられる見方があります。

  • 「それは良いことです。テストは現実的である必要があり、これらのデータ制約は本番環境に存在します。」
  • 「それは悪いことです。他の部分を含まずにシステムのテスト部分をユニット化できるはずです。システム全体の統合テストを追加できます。」

テストの実行中に外部キーのチェックを一時的にオフにすることもできます。MySQLは、少なくともこれをサポートしています。


私は通常、ここで真ん中の道に行きます:私はFKを使用してから、さまざまなテストシナリオをサポートするようにDBを設定する単体テストヘルパーメソッドを記述します。これらのテーブルにデータを入力する必要があります。
joelpt 2014

おそらく、関連のないエンティティ間でリンクテーブルを使用する必要がありました。またはさらに進んで-個別のDBS:各要素(クライアント、アカウント、トランザクション)が異なるシステムであり、異なるDBを持つサービス指向アーキテクチャーまたはマイクロサービスの状況を検討してください。それらの間にはFKはありません。この場合、FKを使用して、データのタイプごとにサブテーブル内の孤立したデータを防止する必要があります。
JeeBee 2014

3
制約のためにできるようにDBMSもあり延期あなたが全体のトランザクションをコミットすると、挿入、更新、削除の順序は問題ではないので、彼らは唯一、チェックされるように
a_horse_with_no_name

2
ビジネス層からの更新をテストする場合、開発環境にはFKが存在する必要があります。レコードを更新するときは、更新を成功させるために必要な列の値が必要です。そうでなければ、私見あなたのテストは有効ではありません。
KeyOfJ 2015年

3
データベースは単体テストに関与すべきではなく、それらを模擬する必要があります。統合テストではそれらが関係しますが、外部キーに起因する問題は、修正しない限り、ユーザーにも発生します。
AndreasBergström2017

16

「レコードの削除がより面倒になる可能性があります。外部キーがその制約に違反する他のテーブルにレコードがある場合、「マスター」レコードを削除することはできません。」

SQL標準では、外部キーが削除または更新されたときに実行されるアクションが定義されていることに注意してください。私が知っているのは:

  • ON DELETE RESTRICT-この列にキーを持つ他のテーブルの行が削除されないようにします。これは、ケンレイが上で説明したものです。
  • ON DELETE CASCADE -他のテーブルの行が削除された場合、それを参照しているこのテーブルの行を削除します。
  • ON DELETE SET DEFAULT -他のテーブルの行が削除された場合、その行を参照するすべての外部キーを列のデフォルトに設定します。
  • ON DELETE SET NULL -他のテーブルの行が削除された場合、このテーブルでそれを参照しているすべての外部キーをnullに設定します。
  • ON DELETE NO ACTION-この外部キーは、それが外部キーであることを示すだけです。具体的には、ORマッパーで使用します。

これらと同じアクションがにも適用されON UPDATEます。

デフォルトはどちらに依存するようです 使用しているサーバー。


14

@強調-これはまさにメンテナンスの悪夢を引き起こすような考え方です。

宣言的な参照整合性を無視するのはなぜでしょうか。せいぜい弱い予防策である、いわゆる「ソフトウェアの強制」を優先して、データが少なくとも一貫していることが保証されます。


関係する開発者は、自明ではない、正規化された関係モデルを要求する問題に取り組んだことがないからです。多くの問題、特に今日流行しているWeb /「ソーシャルメディア」タイプのプログラミングに多く見られるような問題はありません。ORMフレームワークのバックエンドをドリブルして何かがアルファ版の問題を満たしている場合、誰もがデータモデリングについてもっと考えることはないでしょう。そのような問題の多くは、K / Vストア、ドキュメントデータベース、または単純なオブジェクトのシリアル化と同様に簡単に処理できます。
zxq9 2014

12

それらを使用しない理由は1つあり ます。それらの役割や使用方法を理解していない場合です。

間違った状況では、外部キーの制約により、事故がウォーターフォールで複製される可能性があります。誰かが間違った記録を削除した場合、それを元に戻すことは巨大な作業になる可能性があります。

また、逆に、何かを削除する必要がある場合、設計が適切でないと、制約によってあらゆる種類のロックが発生し、それが妨げられます。


8
バックアップなしで本番環境で行を削除することは、有効な引数ではありません。それらを理解していない場合は、省略せずに学習することを検討してください。
ギヨーム

2
@ギョーム私は彼の答えは少し皮肉であり、文字通りに取られるべきではないと思います:あなたがそれらを理解していないなら、それらを使わないでください。しかしもちろん、それらを理解し、使用する必要があります。
ベンジャミン

^これ。これらは便利なツールですが、初心者の手には危険なツールです。
ケントフレドリック2017

11

それらを使用しない正当な理由はありません ...孤立した行があなたにとって大した問題でない限り、私は推測します。


11
孤立した行が重要なのはなぜですか?
Seun Osewa 2010

2
マルチスレッドについてはどうですか?特定の状況では、マルチスレッド化の悪夢を引き起こす可能性があります。互いに参照する必要のあるオブジェクトに遭遇する可能性のあるデータベースを書き込む複数のスレッドを持つ複雑なアプリケーションでは、特にテーブルが後で静的になる場合は、ビジネスロジックで参照整合性を制御することをお勧めします。
Keith Pinson、2011

同意する。また、無慈悲に破棄するよりも、後で復旧できるophan行を使用することを好みます。
PedroD 2016

4

より大きな質問は:あなたは目隠しをして運転しますか?これが、参照制約のないシステムを開発する場合の方法です。ビジネス要件の変更、アプリケーション設計の変更、コードのそれぞれの論理的仮定の変更、ロジック自体のリファクタリングなどが可能であることを覚えておいてください。一般に、データベース内の制約は、現代の論理的な仮定の下に配置され、特定の論理的なアサーションおよび仮定に対して一見正しいように見えます。

アプリケーションのライフサイクルを通じて、特に新しい要件が論理アプリケーションの変更を駆動する場合、参照とデータチェックの制約により、アプリケーションを介したデータ収集が制限されます。

このリストの主題では、外部キー自体は「パフォーマンスを向上させる」ことも、リアルタイムトランザクション処理システムの観点から大幅に「パフォーマンスを低下させる」こともありません。ただし、大量の「バッチ」システムでの制約チェックには総コストがかかります。つまり、リアルタイムとバッチのトランザクションプロセスの違いです。バッチ処理-順番に処理されるバッチの、制約チェックによって発生するコストの合計がパフォーマンスに影響を与える場合。

適切に設計されたシステムでは、データの整合性チェックは、バッチを処理する「前」に行われます(ただし、ここでもコストがかかります)。したがって、ロード時に外部キー制約チェックは必要ありません。実際、外部キーを含むすべての制約は、バッチが処理されるまで一時的に無効にする必要があります。

クエリのパフォーマンス -テーブルが外部キーで結合されている場合は、外部キーの列にインデックスが付けられていないことを認識してください(ただし、それぞれの主キーには定義によりインデックスが付けられます)。さらに言えば、任意のキーにインデックスを付けて外部キーにインデックスを付け、テーブルをインデックス付きで結合することで、外部キー制約のある非インデックスキーで結合するのではなく、パフォーマンスの向上に役立ちます。

サブジェクトを変更します。データベースがWebサイトの表示/コンテンツのレンダリングなどをサポートし、クリックを記録している場合、すべてのテーブルに完全な制約があるデータベースは、そのような目的のために強制終了されます。それについて考えてください。ほとんどのウェブサイトはそのためにデータベースを使用していません。同様の要件で、データが記録されているだけで、言うまでもなく参照されている場合は、制約のないメモリ内データベースを使用します。これは、データモデルがないこと、論理モデルがないこと、物理データモデルがないことを意味しません。


ええと、なぜ空白の代わりに3つの二重改行を挿入し、2つの単語を変更するのが'67%はジョナサンレフラー 'であるのかはわかりませんが、これほど多くの作業を行ったとは思いません。本文は@jay(ユーザー183837)によって寄稿されました。
ジョナサンレフラー、

私は、他のほとんどのサイトの場合のように、パラグラフはここでは機能しないと思いました。したがって、フローの変更に太字を使用して、すべてを1つにまとめました。
jasbir L

3

外部キーを使用するその他の理由:-データベースをより多く再利用できます

外部キーを使用しない追加の理由:-再利用を減らすことで顧客をツールに閉じ込めようとしています。


3

私の経験では、データベースクリティカルアプリケーションでFKを使用しない方が常に良いです。FKは良い習慣だと言っている人たちには反対しませんが、データベースが巨大で、1秒あたりのCRUDオペレーションが膨大な場合は現実的ではありません。名前を付けなくても共有できます...の最大の投資銀行の1つは、データベースに単一のFKを持ちません。これらの制約は、DBに関連するアプリケーションを作成するときにプログラマーによって処理されます。基本的な理由は、新しいCRUDが実行されるときは常に、複数のテーブルに影響を与え、各挿入/更新を確認する必要があることですが、これは単一行に影響するクエリでは大きな問題にはなりませんが、処理するときに大きな遅延が発生します大手銀行が日常業務として行わなければならないバッチ処理。

FKを回避する方が適切ですが、そのリスクはプログラマーが処理する必要があります。


8
大銀行の開発慣行が黄金の基準を設定するとは思いません。
Adriaan Koster、2015

3

「レコードを追加する前に、対応するレコードが別のテーブルに存在することを確認する」がビジネスロジックです。

データベースでこれを望まないいくつかの理由を次に示します。

  1. ビジネスルールが変更された場合は、データベースを変更する必要があります。多くの場合、データベースはインデックスを再作成する必要があり、これは大きなテーブルでは低速です。(変更ルールには、ゲストがメッセージを投稿したり、コメントを投稿したにもかかわらずユーザーが自分のアカウントを削除することを許可するなど)が含まれます。

  2. データベースの変更は、変更を本番リポジトリにプッシュしてソフトウェア修正を展開するほど簡単ではありません。データベースの構造をできるだけ変更しないようにしたいと思います。データベース内のビジネスロジックが多いほど、データベースを変更する(および再インデックスをトリガーする)必要性が高まります。

  3. TDD。単体テストでは、データベースをモックの代わりに使用して、機能をテストできます。データベースにビジネスロジックがある場合は、完全なテストを実行していないため、データベースでテストするか、テスト目的でコードにビジネスロジックを複製して、ロジックを複製し、ロジックが機能しない可能性を高める必要があります。同じ方法。

  4. さまざまなデータソースでロジックを再利用する。データベースにロジックがない場合、アプリケーションはデータベースのレコードからオブジェクトを作成し、Webサービス、jsonファイル、またはその他のソースからオブジェクトを作成できます。データマッパーの実装を入れ替えるだけで、すべてのビジネスロジックを任意のソースで使用できます。データベースにロジックがある場合、これは不可能であり、データマッパーレイヤーまたはビジネスロジックにロジックを実装する必要があります。どちらの方法でも、コードにこれらのチェックが必要です。データベースにロジックがない場合は、さまざまなデータベースまたはフラットファイル実装を使用して、アプリケーションをさまざまな場所にデプロイできます。


2

データの一貫性を維持するのに役立つという点で、以前の回答に同意します。しかし、数週間前に、正規化された一貫性のあるデータの長所と短所について議論した興味深い投稿がJeff Atwoodにありました。

一言で言えば、非正規化されたデータベースは、大量のデータを処理するときに高速になることがあります。また、アプリケーションによっては正確な一貫性を気にする必要はありませんが、DBの場合とは異なり、データを処理するときはより注意深く行う必要があります。


ジェフはいくつかの良い点を作ります。ただし、「Enterprise Rails」のDan Chakは、データの非正規化されたコピーであるキャッシュテーブルを設計する方法を示しています。クエリは高速に実行され、テーブルを更新する必要がない場合は、うまく機能します。データがアプリケーションの動作(アプリケーションの状態など)を左右する場合、データの不整合はアプリケーションの動作の不整合につながるため、データをできるだけ正規化する必要があることがわかりました。
ジェイゴッセ

正規化されていないデータウェアハウス、予想される一貫したアクセスパスで大量のデータ読み取る場合に役立ちます。他のすべてのシナリオでは、これは危険な誤りです。
Peter Wone 2013年

2

Clarifyデータベースは、主キーまたは外部キーを持たない商用データベースの例です。

http://www.geekinterview.com/question_details/18869

おもしろいのは、技術ドキュメントは、テーブルがどのように関連しているか、テーブルを結合するためにどの列を使用するかなどを説明するために非常に長くなっていることです。

つまり、明示的な宣言(DRI)を使用してテーブルを結合できた可能性がありますが、結合しないこと選択しました

その結果、Clarifyデータベースは不整合でいっぱいになり、パフォーマンスが低下します。

しかし、削除、追加の前に関連する行をチェックするなどの参照整合性を処理するコードを記述する必要がなく、開発者の作業が容易になったと思います。

そして、それが、リレーショナルデータベースに外部キー制約がないことの主な利点です。それは、少なくともそれが悪魔かもしれないケアの観点から、開発をより簡単にします。


失敗した参照整合性チェックを処理するコードは、一貫性のないデータを処理するコードよりもはるかに小さくなります。
ジェイゴッド

@ジェイ同意!私がこのアプローチを主張しているとは思わないでください。
エドギネス2010年

2

私はOracleデータベースのみを知っており、他のデータベースは知りません。外部キーはデータの整合性を維持するために不可欠であると言えます。データを挿入する前に、データ構造を作成し、正しく作成する必要があります。これが完了すると、主キーと外部キーがすべて作成され、作業が完了します。

意味:孤立した行?いいえ、私の人生でそれを見たことはありません。悪いプログラマが外部キーを忘れたり、別のレベルで実装したりしない限り。どちらも-Oracleのコンテキストでは-データの重複、孤立データ、つまりデータの破損につながる大きなミスです。FKが適用されていないデータベースは想像できません。私には混乱のようです。これはUnixの許可システムに少し似ています。誰もがrootであると想像してください。混乱を考えてみてください。

主キーと同様に、外部キーは必須です。それは言っているようなものです:主キーを削除するとどうなりますか?まあ、完全な混乱が起こるでしょう。それがそうです。主キーまたは外部キーの責任をプログラミングレベルに移動することはできません。データレベルで行う必要があります。

欠点?そのとおり !挿入時には、さらに多くのチェックが行われるためです。ただし、データの整合性がパフォーマンスよりも重要である場合、それは非常に簡単です。Oracleでのパフォーマンスの問題は、PKおよびFKに付属しているインデックスに関連しています。


1

それらはレコードの削除をより厄介なものにする可能性があります-外部キーがその制約に違反する他のテーブルにレコードが存在する「マスター」レコードを削除することはできません。トリガーを使用して、カスケード削除を行うことができます。

主キーを不適切に選択した場合、その値を変更することはさらに複雑になります。たとえば、個人の名前として「customers」テーブルのPKがあり、そのキーを「orders」テーブルのFKにすると、顧客が名前を変更したい場合、それは非常に苦痛です。 。しかし、それは単なるお粗末なデータベース設計です。

私は、fireignキーを使用することの利点が、想定されるあらゆる欠点を上回ると信じています。


5
とにかく、めったに削除しない傾向があります。「可視/アクティブ」ビットをマークするだけです。
Dana、

「fireignのキーを使用することの利点は、想定される欠点よりも優れていると考えています」
Ian Boyd

2
主キーの値を変更することはありません。あなたは、削除行全体をして再作成違って。変更する必要があると思う場合、スキーマに欠陥があります。
DanMan

外部キーがCustomerId(PK)に設定されている場合、顧客名を変更することはまったく面倒ではありません。注文テーブルで。これが問題になる唯一の方法は、FKがCustomerNameに設定されている場合で、これは決して当てはまりません。私見
KeyOfJ

1

外部キーの制約の検証にはCPU時間を要するため、外部キーを省略してパフォーマンスを向上させる人もいます。


6
重複した一貫性のないデータの削除に費やされるCPU時間はどれくらいですか?
Ed Guiness

ええ、これは本当です。私が取り組んでいるシステムでは、一度に10〜40ギガのデータをデータベースに挿入する必要があり、FKパフォーマンスの有無にかかわらず、合計時間がかかります。
ポールメンドーサ、

1

私もこの議論を聞いたことがあります。外部キーにインデックスを付けるのを忘れて、特定の操作が遅いと不平を言った人からです(制約チェックがインデックスを利用できるため)。まとめると、外部キーを使用しない正当な理由はありません。最新のデータベースはすべてカスケード削除をサポートしているので...


9
FK制約が一部で使用されていない本当の理由(ほとんどの場合、私の観点から)は、パフォーマンス節約の引数で怠惰を守ることができるというふりをしていることです。私の会社が被る愚かさの費用の大部分は、FK制約の強制の欠如と、これが会社を通じてもたらす波及効果によるものだと私は固く信じています。一意のキーの欠如は、12レベルの入れ子になったIFとランダムインデントを使用して2000行以上のストアドプロシージャの横にあるもう1つの原因ですが、ここで止めます。
チャド

1

私が聞いた議論は、フロントエンドがこれらのビジネスルールを持つべきだということです。そもそも制約を破るような挿入を許可してはならない場合、外部キーは「不要なオーバーヘッドを追加」します。これに同意しますか?いいえ、しかしそれは私がいつも聞いたことです。

編集:私の推測では、彼は概念として外部キー制約ではなく、外部キー制約を参照していました。


いいえ。彼は実際の鍵が好きではありません!
ljs 2008

それは私を驚かせます。外部キー制約を好まないことと外部キーを好まないことの間には大きな違いがあります。あなたがそれらなしでリレーショナルデータベースをどのように持っているかはわかりません。
lordscarlet 2008

はい、彼の話を聞いてショックを受けました。しかし、彼は意図せずにほほえんでいたかもしれません。多分彼はここに投稿し、ある段階で明確にするでしょう:-)
ljs

1

私にとって、ACID標準に準拠したい場合は、参照整合性を確保するために外部キーを用意することが重要です。


1

ここでコメントの2番目に挙げる必要があります。外部キーは、データの整合性を確保するために必要なアイテムです。ON DELETEとON UPDATEの異なるオプションを使用すると、人々がその使用に関してここで言及する「ダウンフォール」のいくつかを回避できます。

私のすべてのプロジェクトの99%で、データの整合性を強制するためにFKを持っていることに気づきましたが、クライアントが古いデータを保持しなければならないまれな状況があります。しかし、とにかく有効なデータのみを取得するコードを書くのに多くの時間を費やしているので、無意味になります。


1

アプリケーションのライフサイクル全体の保守性と不変性はどうですか?ほとんどのデータは、それを利用するアプリケーションよりも寿命が長いです。関係とデータの整合性は非常に重要なので、次の開発チームがアプリのコードで正しく理解できるように期待することはできません。自然な関係を尊重しないダーティデータのあるデータベースで作業していない場合は、そうします。データの整合性の重要性が非常に明確になります。


1

また、ほとんどのデータベースでは外部キーが必要だと思います。唯一の欠点(一貫性の強制に伴うパフォーマンスへの影響を除く)は、外部キーがあると、機能的な外部キーがあると想定してコードを記述できることです。それは決して許されるべきではない。

たとえば、参照先のテーブルに挿入し、最初の挿入が成功したことを確認せずに参照元のテーブルへの挿入を試みるコードを書く人を見てきました。後で外部キーが削除されると、データベースの一貫性が失われます。

また、更新または削除時に特定の動作を想定するオプションもありません。外部キーが存在するかどうかに関係なく、必要なことを実行するコードを作成する必要があります。カスケードされていない削除がカスケードされていると想定すると、削除は失敗します。参照されている列への更新が参照されている行に反映されていない場合、それらが反映されていると想定すると、更新は失敗します。コードを記述するために、これらの機能がない場合もあります。

これらの機能がオンになっている場合、コードはとにかくそれらをエミュレートし、パフォーマンスが少し失われます。

したがって、概要....一貫したデータベースが必要な場合は、外部キーが不可欠です。外部キーは、作成するコードに存在するか、機能していると決して想定しないでください。


1

私はドミトリーの答えをエコーし​​ます。

FKがもたらすパフォーマンスオーバーヘッドが心配な場合は、挿入、削除、または更新中の制約検証のコストオーバーヘッドなしに、FK制約のクエリオプティマイザーの利点を得る方法があります(Oracle)。つまり、属性RELY DISABLE NOVALIDATEを使用してFK制約を作成します。つまり、クエリオプティマイザーは、データベースが実際に制約を適用することなく、クエリの作成時に制約が適用されていると想定します。このようにFK制約をテーブルに設定する場合、責任を負うためにここで非常に注意する必要があります。これは、FK列に制約に違反するデータがないことを確実にするためです。このFK制約がオンになっているテーブルを含むクエリから、信頼できない結果が得られる可能性があります。

通常、この戦略はデータマートスキーマの一部のテーブルで使用しますが、統合ステージングスキーマでは使用しません。データのコピー元のテーブルに同じ制約が既に適用されていることを確認します。または、ETLルーチンが制約を適用します。


1

ここで答える人々の多くは、参照制約を介して実装される参照整合性の重要性に夢中になっています。参照整合性を備えた大規模なデータベースでの作業は、うまく機能しません。Oracleは、削除のカスケードが特に悪いようです。私の経験則では、アプリケーションはデータベースを直接更新してはならず、ストアドプロシージャを介して行う必要があります。これにより、データベース内のコードベースが維持され、データベースが整合性を維持することができます。

多くのアプリケーションがデータベースにアクセスする可能性がある場合、参照整合性の制約のために問題が発生しますが、これは制御にかかっています。

アプリケーション開発者は、データベース開発者が必ずしもそれほど精通していない可能性がある非常に異なる要件を持っている可能性があります。


5
「アプリケーションは、データベースを直接更新してはならず、ストアドプロシージャを介して実行する必要があります。これにより、データベース内にコードベースが保持され、データベースの整合性が維持されます。」<-ここでは、ストアドプロシージャのロジックがデータの整合性に違反することはできないという仮定がありますが、これはまったく間違っています。
Tim Gautier

1

基本的に1つのデータベースシステムが将来変更されないことが確実である場合は、外部キーを使用してデータの整合性を確保します。

しかし、ここに、外部キーをまったく使用しない非常に良い現実的な理由があります。

さまざまなデータベースシステムをサポートする製品を開発しています。

多くの異なるデータベースシステムに接続できるエンティティフレームワークを使用している場合は、「オープンソースの無料」サーバーレスデータベースをサポートすることもできます。これらのデータベースのすべてが外部キールール(行の更新、削除など)をサポートしているとは限りません。

これにより、さまざまな問題が発生する可能性があります。

1.)データベース構造が作成または更新されると、エラーが発生する場合があります。おそらく、外部キーはデータベースシステムによって無視されるだけなので、サイレントエラーのみになる可能性があります。

2.)外部キーに依存している場合は、ビジネスロジックでデータ整合性チェックをほとんどまたはまったく行わないでしょう。ここで、新しいデータベースシステムがこれらの外部キールールをサポートしていない場合や、別の方法で動作している場合は、ビジネスロジックを書き直す必要があります。

あなたは尋ねるかもしれません:誰が異なるデータベースシステムを必要としますか?まあ、誰もが自分のマシンで本格的なSQL Serverを購入できるわけではありません。これはソフトウェアであり、保守する必要があります。他の人たちはすでに他のDBシステムに時間とお金を投資しています。サーバーレスデータベースは、1台のマシンのみを使用する小規模なお客様に最適です。

これらのすべてのDBシステムがどのように動作するかは誰にもわかりませんが、整合性チェックを行うビジネスロジックは常に同じままです。


0

それらを使わないのは面倒だといつも思っていました。私はそれが常に行われるべきであると教えられました。しかし、その後、私はジョエルの議論に耳を傾けませんでした。彼には正当な理由があったのかもしれませんが、私にはわかりません。


ディスカッションというよりは、単なる口外発言でしたが、おそらく、彼が独立してこのテーマについて考えていることを正確に調査する必要があります。しかし、このトピックに関するコミュニティの意見にも興味がありました。
ljs 2008

0

FKで問題が発生する可能性があるのは、(参照テーブルで)キーを参照する履歴データがあり、キーを使用可能にしたくない場合です。
明らかに解決策は、物事をよりよく前もって設計することですが、ここでは、常に完全なソリューションを制御できるわけではない現実の状況を考えています。
例:customer_typeさまざまなタイプの顧客をリストしたルックアップテーブルがある場合-特定の顧客タイプを削除する必要があるが、(ビジネス上の制約により)クライアントソフトウェアを更新できず、誰もこの状況に気付いていないソフトウェアを開発するとき、それが他のいくつかのテーブルの外部キーであるという事実は、それを参照する履歴データが無関係であることを知っていても、行を削除できない場合があります。
これで数回焦らされた後、おそらく関係のdb施行から身を乗り出すでしょう。
(私はこれが良いと言っているのではありません-FKとdbの制約を一般的に回避することを決定する理由を与えるだけです)


あなたが何を言おうとしているのか理解できれば、それに対する私の答えは、ルックアップテーブルのレコードを論理的に削除するか、不要になった履歴データをアーカイブし、ルックアップレコードもアーカイブすることだと思います。
Chad
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.