web-dev-qa-db-ja.com

関係のない関係の完全性

リレーショナルデータベースを使用してビジネスソフトウェアを作成するソフトウェアエンジニアリングの約15年の経験があります。主にSQL ServerとOracle。私は常に、データベースでリレーションを定義し、データベースにリレーショナル整合性を処理させるべきであるという意見を持っています。そして私の場合、99.9%の時間で一意のID列を主キーとして使用しています。

私の意見はまとまらないので、私たちが作業しているアプリケーションについていくつかアドバイスをお願いします。これは、私のアプリケーションとのインターフェースが必要なサードパーティのアプリケーションです。どちらのアプリケーションもデータベースとしてSQL Serverを使用します。データを送信および取得するためのインターフェースはありません。そのため、データベーススキーマの一部と、SQLクエリを使用してデータを保存する方法について説明してくれました。

送信されたスキーマから、リレーションを使用しておらず、ほとんどの場合、主キーのID値を使用していないことが明らかでした。彼らとのコミュニケーションをフォローする際に、彼らはアイデンティティ列は例外ではなく、標準であるとほとんど言っていました。また、コード内のすべての参照整合性を処理すると述べました。

彼らが恐ろしい間違いを犯したと私はかなり確信している。たとえば、このデータベースにデータを保存する必要があり、アプリに「参照整合性コード」がありません。そして、誰かがデータベースで直接いくつかのクエリを実行しなければならない場合、それも問題を引き起こします。これはメンテナンスの悪夢だと思います。

誰かがこのベンダーが下した決定を客観的にサポートするために合理的な議論をすることができますか?何らかの理由で思い付くのに苦労しています。

6
Dan

このような設計上の決定の理由は、多くの場合、技術的なものではなく、組織的なものです。これが現実の世界で、次のような状況で発生するのを見てきました。

  • システムが設計された時点では、データベースに排他的にアクセスできるアプリケーションは1つしかないため、最初は参照制約とID列はそれほど重要ではありません。

  • システムの開発者は、アプリケーション開発について十分な訓練を受けていますが、データベース設計についてはあまり訓練を受けていません。

  • 通常、設計者は「特別な場合の例外」を簡単に実装できないため、データベースの参照整合性制約にいくつかの悪い経験をした可能性があります。このような例外はアプリケーション側で処理する方がはるかに簡単です。

    例:「テーブルAのこの列は、テーブルBのID列へのnullではない外部キー参照である必要があります」-そして誰かが「ああ、テーブルAのisTemplate列がtrueである場合を除いて」と言います。 DB側の要件では、FK制約を多少とも複雑なDBトリガーで置き換える必要があります。

  • -=通常は非常に良い-のアプローチ "最初に最も簡単な作業ソリューションから始めて、後で改善する"まずDBで関係なしで開始し、後で追加しますの代わりに)厳密な制約で開始し、後で厳密性を低くします)。

残念ながら、システムが参照整合性なしでビルドされ、最初のバージョンが本番環境に入ると、遅かれ早かれ、いくつかの賢明な制約を有効にしてデータベースに挿入できなかった多くのデータが含まれます。

その後、それらの制約を後でdbに追加するのが難しくなります。多くの場合、開発者がアプリケーションを変更して、この「低品質」のデータを処理するように変更する方が簡単です。そのため、データを修正するために必要な「データ改善プロセス」を開始する代わりに、データをデータベース内で未変更のままにすることができます。 DB側の問題ですが、ユーザーと管理者によるサポートが必要な場合があります。

もちろん、システムが成長し、DBにアクセスする複数のアプリケーション、特にデータを書き込むアプリケーションが複数になるように拡張された場合、DBの設計をより厳格にした方が良い点は確かにあります。 。しかし、後の方がそこに到達しようとすると、それは難しくなります。

12
Doc Brown

これは、多くの業界でますます見られる傾向です。データの冗長性についてはるかに楽観的な、よりフラットなデータ構造です。

おそらく、このことを考えてもそれほど驚いてはいけません。

  • ストレージは安価で、CPUは高速で、メモリは豊富です。つまり、データの冗長性はパフォーマンスの問題のはるかに少ないです
  • .NET言語でのLINQの登場により、データのスライスとダイシングがクライアント側ではるかに簡単になりました
  • 過去の確立された教義に対する現代言語のよりリラックスした性質。 (PythonのZenから)フラットはネストよりも優れています

約5年前にDoc Brownの回答の要点に完全に同意したはずですが、それはほんの一部にすぎません。それ以来、ソフトウェア開発とデータベースの両方の分野で多くの変化がありました。

数年前に、Facebookの非リレーショナルDB構造がRDBMSの世界の第一人者に「それはうまくいかず、決して拡大しない」と非難されたニュース記事を思い出します。それ以来私たちが見てきたように-それは実際に行われました。

2
Robbie Dee

私はよく、DBの参照整合性、つまりFK制約をスキップします

しかし、私は常にユニークなPKを持っています。

ですから私の場合、それはすべてに対して厳密な関係の欠如に似ています。確かにあなたは顧客のいない顧客の住所を持つことができます-自分をノックアウトしてください。機能しないビットを除いて、すべてが機能します。

さらに、DBをAPIの背後に隠して、強制が必要な関係を強制できるようにします。

これは、どのような場合でも制約をアトミックに適用できず、潜在的なエラーに対処する必要がある分散データでうまく機能します。

ベンダーはIDを持たないことでさらに一歩進んでいますが、寛大に、一意の複合キーがあると仮定しましょう。理論的にはそれも同様に機能します。

ただし、APIをバイパスして直接アクセスすることもできます。 DBレベルで厳密な制約があったとしても、これは依然として疑わしいものです。 DB内のすべてのルールを適用することはできないため、実際に試行した場合、それを破ることができます。

この場合、APIの欠如が主要な罪である場合、サードパーティのソフトウェアへのこの低レベルのアクセスを要求するには、虫眼鏡の下にいる必要があると思います。

本質的に悪いというよりは、このソフトウェアには必要な機能が欠けているようです。

1
Ewan

本当の問題は何ですか?

ここでの本当の問題は、参照整合性やその他の重要な制約がないことではありません。それは、アプリケーションに送信されるデータの適切な検証を保証せずにデータベースがインターフェイスメディアとして使用されるという事実です。

遅かれ早かれ、これは矛盾につながります:

  • データベースの制約は、データが追加されるときに最小限の一貫性を保証することにより、このような状況を防ぐのに役立ちます。
  • より良いアプローチは、データを取得して使用する前にデータをサニタイズするためのインターフェイス(APIやファイルベースなど)を提供するアプリケーションです。

参照整合性の欠如を説明する歴史的な議論はありますか?

まず第一に、私はあなたの意見を完全に共有することを認めなければなりません。参照整合性はデータの信頼性を強化するだけでなく、オプティマイザにその仕事をするための追加情報を提供します。

そうは言っても、チームは参照整合性に対する歴史的な議論によって誤解を招く可能性があります。

  • 私は1986年にOracle 5での開発を開始しましたが、その時点で、更新用のテーブルロックスキームがありました。 Oracle 7では、1992年以前は参照整合性がありませんでした
  • 一定期間、パフォーマンスを犠牲にして参照整合性がいくつかのDBMSに実装されました(たとえば、外部キーの余分なロックによって同時実行性が低下した1つの例を覚えています)。
  • ベンダー固有の拡張機能が自動化される前の列 2003年のSQL標準 。これにより、列の識別の使用がデリケートなものになりました(クエリ、更新、失敗、再試行など)。したがって、可能な限り、自然な(意味のある)キーが好まれました。たとえば、オーダーIDはほとんど常に一意のIDとして管理されていましたが、オーダーラインアイテムが独自の一意のiDを持つことはほとんどありませんでしたが、IDを組み合わせたもの(実装が簡単なため、オーダーID +ライン番号が好まれました)。または、デバイスによって記録されたすべての測定値に対して、一意のIDではなく、キーデバイスID +タイムスタンプの組み合わせがありました。なぜこれが問題なのですか?このような状況では、参照整合性を使用すると自然キーの変更が非常に困難になったためです(DBがカスケード変更をサポートしていない場合)。

したがって、問題はAS400かどうかではなく、以前に行われた以前の経験です。

参照整合性がない理由はまだありますか?

これらの歴史的な理由は、参照整合性の欠如が時代遅れの慣習のしるしであると考えることにつながりません!

参照整合性を使用しないことを支持するいくつかの正当な理由:

  • データベースの独立性: ドキュメント指向のデータベース (MongoDBなど...)は、構造化されたデータセットを優先しないため、参照整合性を提供しません。そのため、そのようなDBMSを使用するアプリを開発する場合、またはデータベースの独立性を確保したい場合は、アプリケーションの整合性に注意する必要があります。したがって、DBレベルでは実際には気にしません。
  • DDDと値オブジェクト:値オブジェクトは、IDを持たないという点でエンティティーとは異なります。値オブジェクトは、その属性の値によってのみ識別されます。これはSQLに変換されます。これは、値オブジェクトを識別するために一意のIDを使用しないことを意味します。その場合、参照整合性はあまり明白ではないので、最初から始めます。
1
Christophe