web-dev-qa-db-ja.com

実際には外部キー制約を使用しません。大丈夫ですか?

FK制約を使用しないことは、私の会社の秘訣です。 FK制約は、ERDの設計時にのみ使用され、テーブルの作成時には使用されません。

私の先輩によると、実際には、私たちが緊急の問題に対処するとき、それらは非常に時間がかかる障害です。 INSERT/UPDATE/DELETEステートメントをすぐに使用する必要がある場合、制約はこれらのステートメントの実行をブロックし、制約を維持しながらステートメントを書き込むことも時間がかかると彼は言います。他の多くの会社がこれをしているとさえ聞いた。

私はその闘争を少し理解していますが、DBに対する私の理解とは正反対であるため、これが良い方法であるかどうかはわかりません。この会社も私の最初の仕事なので、他の会社がこれをどのように扱っているのかわかりません。

実際に、これについてあなたの意見は何ですか?これは正当化できますか?もっと良い方法はありますか?この問題について他の会社はどうしていますか?

更新:それは韓国企業にとって非常に一般的なアプローチのようです。他の会社で働いていたいくつかの他の先輩に尋ねました、そして彼らのほとんどは彼らがすべてこのようにやっていると言っています。そして、そのうちの一人でも金融会社で働いていました!面白い...

11
user2652379

無料のものはありません。時々何かを持たないことも無料ではありません。外部キーを宣言している場合と宣言していない場合のどちらにも、コストとメリットがあります。

外部キー(FK)の要点は、ここにあるthis列が、そこにあるthat列からの値しか持てないことを保証することです。1。このようにして、実際に生産および販売する製品について、実際に存在する顧客の注文のみを確実に取り込むことができます。多くの人がこれは良いアイデアだと思っています。

それらをDBMS内で宣言する理由は、それらを強制することを処理できるようにするためです。ルールに違反するデータを許可することは決してありません。また、ルールを適用するために必要なデータを取り除くこともできません。このタスクをマシンに委任することにより、データのソースや、いつ書き込まれたか、どのアプリケーションを経由したかに関係なく、データの整合性に自信を持つことができます。もちろん、これにはコストが伴います。 DBMSは、すべての行について、すべてのクエリについて、ルールが常に守られていることを確認する必要があります。これには時間と労力がかかり、サーバーの負荷になります。また、ルールを順守する順序で人間がDMLを送信する必要があります。注文をずる賢く強制する必要がなくなり、その後管理者に追いつきます。いたずらな人間ではありません。まずCustomerを作成し、次にProduct(およびすべての必須行)を作成してから、注文を作成します。

外部キーがなければ、何ができるか、そしてそれを行うことができる順番がはるかに自由になります。問題のある行は削除できますアドホックは、重要なプロセスを完了できるようにします。パニックが終わった後、データを後でパッチすることができます。 INSERTは、FKチェックが行われないため、通常は少し速くなります(時間の経過とともに増加します)。すべてのサポートデータが含まれていることを確認する必要なく、データの任意のサブセットを必要に応じてDBからプルできます。等々。関係者がシステムを知っていて、注意深くメモを取り、適切な調整ルーチンを持ち、結果を理解し、自分で整理する時間があれば、これは絶対に問題ありません。コストは、何かが、どこかで一度見落とされ、データベースがほとんど信用できないジャンクに劣化することです。

一部のチームは、データベースではなくアプリケーションにチェックを入れます。これも機能します。ただし、このアプローチではサーバーの総負荷はほぼ同じ(またはわずかに高い)ように見えますが、どこかでコードのチェックを忘れてしまうリスクははるかに高くなります。 DRIを使用すると、ルールはコンピューターに1回通信され、永久に適用されます。アプリケーションコードでは、新しいプログラムごとに書き直す必要があります。

私の2セント相当については、私はすべて外部キーを使用します。列の値が一致することを定期的に繰り返しチェックするなど、コンピュータが得意なことをコンピュータに実行させます。私たち人間は、新しい興味深いものを夢見ることに集中できます。数か月前にシステムの責任を引き受けたので、ほとんどのテーブルにFKを追加しています。ただし、いくつかは追加しません。これらは、外部ソースからデータを収集する場所です。これらの行を拒否するコストは、不良データを受け入れて後で修正するコストよりも高くなります。したがって、これらのいくつかのテーブルでは、外部キーはありません。私はこれを目の当たりにし、監視と是正手順が整っていることを知っています。

1複数列の外部キー制約の存在を認めます。

22
Michael Green

あなたの先輩はうんざりして間違っています。 FK制約は、データの整合性を保証するための1行のコードです。もっと時間がかかるもの、

  • 文字どおり、宣言型言語の1行のコードです。テーブルをCREATEするときにインラインで外部キーを追加できるため、場合によってはそれよりも少なくなります。
  • または、完全性を仮定し、失敗した仮定の欠点を処理します。

notに外部キー制約を使用し、リレーショナルデータベースを使用する理由はありません。 SQL DBAには2つのジョブがあります。

  • DDLでスキーマを作成します。
  • DMLを使用してスキーマにアクセスします。

スキーマを使用してデータの整合性を確保しない場合は、ジョブの一部をスキップするだけです。トランザクションの本質は、アトミックなオール・オア・ナッシングを保証することです。外部キー制約を使用せずに"all"を定義したいですか?それはピタです。

CREATE TABLE foo ( int a PRIMARY KEY );
CREATE TABLE bar ( int b REFERENCES foo );
CREATE TABLE baz ( int b );

barbazに対してアトミックトランザクションを実行します

  1. foo.aに値(1)を挿入します。値が存在する場合は失敗します。
  2. 他のテーブル(bar.bまたはbaz.b)に同じ値1を挿入し、値がfoo.aに存在しない場合は失敗します。

どちらが時間の節約になりますか?

5
Evan Carroll

ほとんどの場合、DBMSで制約のない外部キーを使用するよりも、外部キー制約を宣言する方が適切です。外部キー制約は参照整合性を維持します。これにより、1つの形式のデータ破損が防止されます。

アプリケーションレベルで参照整合性を適用する代わりに、ほとんどの場合、DBMS制約の場合と同じくらい多くのコンピューターリソースとプログラマーの労力がかかります。

参照整合性を維持しない代替策は、通常、データの破損と信頼できない結果につながります。

最初からサイトのポリシーが誤っていた可能性が非常に高いです。これには例外がありますが、その数は限られています。

2
Walter Mitty

これは実際に自分の状況でテストする必要があるものですが、外部キーのデータの整合性を提供し、カスケードに調べることができるデータをすばやく削除または更新する必要があります。

CREATE TABLE ChildTable (
    id INT NOT NULL IDENTITY(1,1), 
    parent_id INT,
    FOREIGN KEY (parent_id)
        REFERENCES parent(id)
        ON DELETE CASCADE
);
2
MrTCS