データベースの制約はどうなりましたか?


46

RDBMSのデータベースモデルを確認すると、通常、PK / FK以外の制約がほとんどまたはまったくないことに驚かされます。たとえば、パーセンテージは多くの場合型の列に格納されますがinttinyintより適切です)CHECK、値を0..100の範囲に制限する制約はありません。同様にSE.SEでも、チェック制約を示唆する回答は、データベースが制約の間違った場所であることを示唆するコメントをしばしば受け取ります。

制約を実装しないという決定について尋ねると、チームメンバーは次のように応答します。

  • そのような機能がお気に入りのデータベースに存在することすら知らないということです。ORMのみを使用するプログラマからは理解できますが、特定のRDBMSで5年以上の経験があると主張するDBAからはほとんど理解できません。

  • または、アプリケーションレベルでそのような制約を強制し、データベースでそれらのルールを複製することは、SSOTに違反して、良いアイデアではありません。

最近では、外部キーさえ使用されないプロジェクトが増えています。同様に、ユーザーが参照整合性をあまり気にせず、アプリケーションにそれを処理させることを示す、SE.SEに関するいくつかのコメントを見ました。

FKを使用しない選択についてチームに尋ねると、次のように伝えます。

  • たとえば、他のテーブルで参照されている要素を削除する必要がある場合は、PITAです。

  • NoSQLは揺れ動き、外部キーはありません。したがって、RDBMSではそれらは必要ありません。

  • パフォーマンスの点では大したことではありません(コンテキストは通常​​、小さなデータセットで動作する小さなイントラネットWebアプリケーションですので、実際にはインデックスでも大したことはありません。特定のクエリのパフォーマンスが1.5 。〜20ミリ秒)

アプリケーション自体を見ると、次の2つのパターンに体系的に気付きます。

  • アプリケーションは、データベースに送信する前にデータを適切にサニタイズしてチェックします。たとえば102、アプリケーションを介して値をパーセンテージとして保存する方法はありません。

  • アプリケーションは、データベースからのすべてのデータが完全に有効であると想定しています。つまり102、パーセンテージで表示された場合、どこかでクラッシュするか、単にユーザーにそのまま表示され、奇妙な状況になります。

  • クエリの99%以上が1つのアプリケーションによって実行されますが、時間が経つにつれて、スクリプトが表示され始めます。必要に応じてスクリプトを手動で実行するか、cronジョブを実行します。一部のデータ操作も、データベース自体で手動で実行されます。スクリプトと手動SQLクエリの両方に、無効な値が導入されるリスクが高くなります。

そしてここに私の質問が来ます:

チェック制約なしで、最終的には外部キーなしでもリレーショナルデータベースをモデル化する理由は何ですか?


価値のあることについては、この質問と私が受け取った回答(特にThomas Kilianとの興味深い議論)により、データベースの制約についての結論を書いた記事を書くことになりまし


8
私はあなたに感じますが、制約が良いアイデアである理由をすでに知っているようですので、答えの形で追加することはあまりありません。ただし、制約の欠如は新しい現象ではなく、リレーショナルデータベースを十分に理解していない開発者が設計したデータベースで何十年もそれを見てきました。意図的に設計を決定することはめったにないと思います。
ジャックB

1
@JacquesB:「私は何十年もそれを見てきました」という答えを投稿することができます10年、この現象に対する私の見解はおそらく間違っている)。したがって、結論も非常に異なります。
Arseni Mourzenko

1
私たちは多くのクライアントと協力しています。また、新しいバージョンのソフトウェアをリリースするのは簡単ですが、すべてのデータベースを更新するのは面倒です。だからこそ、ソフトウェアにはほとんどの制約があります。ああ、そうです、パーセンテージのtinintintは、パーセンテージが分数になる可能性があるため、しばしば良いアイデアではありません。
ピーターB

1
これまでの回答がそうではないことを示している場合、「主に意見に基づく」として誤って閉じられたため、この質問を再び開くことに投票します。
デビッドアルノ

3
私はあなたと110%です。
ペリアタブレアッタ16年

回答:


28

データベースのさまざまなユースケースを区別することが重要です。

従来のビジネスデータベースは、複数の独立したアプリケーションとサービスによってアクセスされ、許可されたユーザーによって直接アクセスされることもあります。データベースレベルでよく考えられたスキーマと制約を持つことが重要です。そのため、単一のアプリケーションのバグや見落としによってデータベースが破損することはありません。データベースはビジネスに不可欠です。つまり、一貫性のないデータや破損したデータは、ビジネスに悲惨な結果をもたらす可能性があります。アプリケーションが行き来する間、データは永久に存続します。これらは、データベースの一貫性と健全性を確保するために専用のDBAがいる場所です。

しかし、データベースが単一のアプリケーションと緊密に統合されているシステムもあります。スタンドアロンアプリケーションまたは単一の組み込みデータベースを備えたWebアプリケーション。データベースが単一のアプリケーションによって排他的にアクセスされている限り、アプリケーションが正しく機能する限り、冗長な制約を考慮することができます。これらのシステムは、多くの場合、アプリケーションコードに焦点を当てたプログラマーによって開発され、おそらくリレーショナルモデルを深く理解していません。アプリケーションがORMを使用する場合、制約はアプリケーションプログラマーにとってより使いやすい形式でORMレベルで宣言される場合があります。ローエンドでは、MySQLを使用してPHPアプリケーションを持っている、と長い時間のためのMySQLは、すべての基本的な制約をサポートしていませんでしたので、あなたが持っていた一貫性を確保するために、アプリケーション層に依存します。

これらの異なる背景の開発者が出会うと、文化的な衝突が発生します。

このミックスに、分散型「クラウドストレージ」データベースの新しい波が生まれます。パフォーマンス上のメリットを失うことなく、分散データベースの一貫性を維持することは非常に難しいため、これらのデータベースは、データベースレベルでの一貫性チェックを回避し、基本的にプログラマがアプリケーションレベルで処理できるようにします。アプリケーションごとに一貫性要件が異なり、Googleの検索エンジンはサーバー全体の一貫性よりも可用性を優先しますが、給与システムが多くの制約のあるリレーショナルデータベースで実行されることは間違いありません。


5
+!1部屋のゾウに言及する場合:1つのアプリケーションが1つのDBのみを使用し、1つのDBが1つのアプリのみで使用されるという誤った仮定
TulainsCórdova16年

4
@TulainsCórdova、ここの部屋の象はGoogleの給与システムだと思いました。:)
マチャド

5
@Machadoこれは天才です:「私は彼らの給与計算システムが多くの制約のあるリレーショナルデータベース上で動作することを望んでいます。」
Tulainsコルドバ

2
また、アプリケーションコードがACIDではないため、データベースを適切に制約すると便利です。
マシューホワイトニング

3
@MatthewWhitedによって行われたコメントを強調するために、アプリケーションがロックを実行して余分なクエリを実行することなく、ある種の行間/テーブル間の制約を強制することはできません。RDBMSは、はるかに低いコストでこれを行うことができます。
デビッドアルドリッジ

15

最近では、クラウド上の分散環境で実行され、「スケールアップ」ではなく「スケールアウト」する手法を採用するシステムが増えています。eコマースアプリなど、インターネットに接続するオンラインアプリケーションを扱う場合は、さらに重要です。

そうは言っても、スケーリングすることになっているすべてのアプリケーションはCAP定理によって制約されます。そこでは、一貫性、可用性、パーティショントレランス(ネットワークフォールトトレランス)のうち2つを選択する必要があります。

CAP定理を研究することにより、選択の余地はあまりないことがわかりますが、ネットワークを常に100%信頼することは決してできないため、可用性または一貫性を失うことを選択します。

一般に、いくつかのアプリケーションは、ある程度の時間、一貫性を保つ余裕はありますが、ユーザーが利用できないわけにはいきません。たとえば、タイムラインにまったくアクセスできない場合よりも、FacebookまたはTwitterでタイムラインが少し順序付けられていない方が優れています。

したがって、いくつかのアプリケーションは、リレーショナルデータベースの制約を解消することを選択しています。リレーショナルデータベースは、一貫性が非常に優れていますが、可用性が犠牲になっているためです。

個人的なメモ:私も古く、私はデータの一貫性がほとんどの場合第一級の要件であるいくつかの本当に古い金融システムで働いていました、そして、私はデータベース制約の大ファンです。データベースの制約は、何年にもわたる悪い開発や、行き交う開発者のチームに対する最後の防衛線です。

「rebusのエストモード」。一貫性が第一級の要件であるDBの「低レベル」一貫性を使い続けましょう。しかし、時にはそれを手放すことは大きな罪ではありません。

-編集:-

質問には多少の編集があるため、データベースに制約をドロップする別の正当な理由、IMOがあります。マルチデータベーステクノロジーをサポートするようにシステムを設計するゼロから製品を設計する場合、サポートされるデータベースの中で最も一般的な分母を決定し、最終的にすべての制御ロジックを残して、制約の使用をやめることができますあなたの申請。

それは合法ですが、私にとっては灰色の領域でもあります。なぜなら、元の質問で提案されたような単純な制約をサポートしていないデータベースエンジンが今日見つからないからです。


「元の質問で提案されたような単純な制約をサポートしていないデータベースエンジンは今日見つかりません。」MySQLはCHECK制約をまだサポートしていますか?
ビンセントサバード

@VincentSavard、正確なCHECK MS SQLではないかもしれませんが、何らかの制限があります:dev.mysql.com/doc/refman/5.7/en/constraint-invalid-data.html
Machado

@Machado-それは特定の制約に関するものではありませんが、適切な型で表現できないデータがクエリに含まれる場合を特定することと同じです。これは、MySQLが単にそのような値を静かに無視した数年前の状況に対する明確な改善です。
ペリアタブレアッタ16年

1
@PeriataBreatta、副次的に、PostgreSQLが完全に利用可能になり、より高度になったときに、MySQLがWebサイト開発者によって選択された「事実上の」OSSデータベースである理由を完全に理解できませんでした。おそらくインストールが簡単だったのかもしれませんが、わかりません。
マチャド

@machado- 確かではありませんが、初期の頃(90年代半ば)にpostgresよりもmysqlを好む傾向がありました(postgresqlに改名されていませんでした)。 SQLをサポートしていませんでした(初期バージョンではサポートしていなかった-「postquel」と呼ばれる独自のクエリ言語を持っていました-そして、私はその開発について最新の状態を保っていなかったので、SQLサポートを追加したことに気づいていませんでしたmysqlが利用可能になったのと同じ時間)。この誤解が一般的だった場合、その理由だけでmysqlが前進した可能性があります。そして、それが先になると、ネットワーク効果が引き継ぎました。
ペリアタブレアッタ

10

チェック制約なしで、最終的には外部キーなしでもリレーショナルデータベースをモデル化する理由は何ですか?

最初に、ここでは非SQLデータベースについてではなく、RDBMについてのみ説明していることを明確にしましょう。

チェック制約は言うまでもなく、FKやPKのないデータベースをいくつか見ましたが、正直なところ、それらは少数です。おそらく大企業で働いているからでしょう。

私の長年の経験では、いくつかの理由が考えられます。

  • 初心者または趣味のプログラマーの場合、モデリングスキルの欠如
  • データベースの世界と実際に接触することなく、ORM広範囲にまたはほぼ排他的に使用する
  • チームまたは小規模プロジェクトにDBAまたはその他のデータモデリングの専門家が不在
  • 開発の最初の段階でDBAまたはデータモデリングの専門家が関与していない
  • 特定の列が1,2 or 3値としてのみ持つことができる、または「年齢」列>= 0「データベースにビジネスロジックがある」ことを強制するチェック制約でさえも考慮する開発者コミュニティの一部による意図的な設計決定。この節の最近のいくつかの質問と回答を見るとわかるように、デフォルトの句でさえ、データベースに属さないビジネスロジックと見なされています。このように考慮している開発者は、可能な限り少ない制約を使用し、参照整合性や単一性さえもコード内ですべて実行します。これは極端な位置だと思います。
  • RDBMSをキー値ストレージとして使用します。これは、RDBMSテーブルを使用して満たすのに十分な要件があるため、SQL以外の動作をエミュレートするために、キー値リポジトリを分離します。
  • データベースは常に「アプリ」によって書き込まれ、大量のデータの読み込みや、SQLクライアントを介した行の編集または挿入は必要ありません(多くの場合、アプリが挿入した不良データを修正するため)。最良の場合のシナリオでは、データベースにDML命令を発行する別のアプリ(「アプリ」以外)が常に存在します:SQLクライアント。
  • データがアプリではなくビジネス所有者のものであることを認識してません。

そうは言っても、RDBMSは巨人の肩越しに構築された非常に高度なソフトウェアであり、多くのビジネス要件に対して非常に効率的であり、一連の参照整合性を強制する日常的なタスクのプログラマーを解放します。バイナリファイルまたはテキストファイル。私がいつも言うように、「私たちはもはや1つのアプリで1つのデータベースの世界に住んでいない」。少なくとも、SQLクライアントは「アプリ」以外にDMLを発行します。したがって、データベースは、人的エラーまたはプログラミングエラーから妥当な範囲で自身を保護する必要があります。

RDBMSが適切にスケーリングされない、よく知られているタイプの要件では、必ず非SQLテクノロジーを採用してください。しかし、RDBMSがより効率的な方法で何を強制するかを強制するために何千行ものコード(生成または型付け)が費やされるという制約のないリレーショナルデータベースの急増を心配しています。


3

技術決定を推進する外部の制約があります。データベースフィールドの制約を定期的に使用する必要性や贅沢がある状況はほとんどありません。

  1. 企業には、DBAとともにアプリとデータベースの両方の開発者がいますが、ほとんどの開発者はこのタイプの環境では働きません。コードでできる限りのことを行います。また、データベース側の一部は、ビジネスルールに関与しません。彼らは主に物事を実行し続けるためにあります。データベースの制約をプッシュすることはありません。従来のアプリ、統合、移行、合併、買収に対処するために、db制約が最適なソリューションになる場合があります。
  2. dbをオーバーロードするとボトルネックが発生する可能性がありますが、問題にさらにマシンを投入することでは簡単に解決できません。パフォーマンスが大幅に低下することなく、db言語がプログラミングの問題を処理しない状況がいくつかあります。そのため、すべてに制約を使用することを計画することはできません。Stackoverflowには1つのデータベースサーバーがあります。問題に2を投げるのは難しいからです。
  3. 自動テスト-彼らはそこに着いていますが、多くのdb開発者はIDE /テストフレームワークとともにパーティーに遅れています。
  4. デプロイメント-より多くのdbスタッフがそれをより複雑にします。制約に違反するデータがあるため、クライアントのデータベースの更新が許可されない場合はどうなりますか?これに対処する方法がない限り、ゲームオーバー。アプリでは、必要に応じてユーザーにこれを処理させるか、管理者にバッチで行うように指示することができます。
  5. app / api / serviceのみがデータベースにデータを書き込むので、なぜ面倒なのですか?これはほとんどの時間を保持するため、一般的ではありません。
  6. dbエラーを処理することは、何百もの制約違反がなければ、すべてが正常に機能しない場合に対処するのに十分なほど困難です。

多くの開発チームは、db開発者にあまり多くの制御を与えたくありません。1つ以上取得する場合は幸運なので、休暇はとても楽しいです。データベースドメインを完全に制御する必要がなく、すべてのクエリ、ビジネスルール、パフォーマンス、可用性、セキュリティ、およびどのデータがどのRAIDに送られるかについて責任を負うものは多くありません。以下は、実行を許可されているストアドプロシージャです。楽しんで。テーブルに触れることさえ考えないでください。


2

これは、私のキャリア(40年近く)で苦労してきた問題であり、DBMSを作成する際にも問題です。私のエンドポイントの説明はこちらです:http://unibase.zenucom.com。だからここに私の考えがあります。

  1. 一般的に、ほとんどの制約はアプリケーションで適切に処理されるため、アプリケーションのさまざまな部分でさまざまな制約を適用できます。たとえば、州コードはすべての管轄区域に適用されるわけではありません。
  2. 余談ですが、%には注意してください。マークアップが100%を超えているか、壊れています:)
  3. 制約は否定的に説明するのが最適です。すなわち、あるべきではなく、あるべきではないもの。常によりシンプルなリストです。
  4. 外部キーは常に適切であり、使用する必要があります。フルストップ。FKはRDBMSの数少ないセマンティックコンストラクトの1つであり、非常に便利です。最大の難しさは、FKが削除された場合に値をぶら下げるか、FKレコードを削除しない理由として従属行を使用するかを決定することです。
  5. 通常、実世界の制約は、単一のフィールド値の制限よりも複雑です。
  6. 一部の制約は、アプリケーションレベルでも、適切な操作に対して機能します。例えば、積極的な日付チェックは、明らかに良い日付のエラーを隠します。賢明な日付のエラーを測定するには、オペレーターのエラーが必要です。

1

データベース制約は賢明なアイデアだったかもしれませんが、それらの実用的な使用についてはどうでしょうか?割合の制約を守ってください。それを適用すると、DBは無効な割合を喜んで拒否します。その後?例外を処理するにはビジネスロジックが必要になります。実際には、間違った割合を記述するビジネスロジックが既に他の場所で失敗していることを意味します。要するに、残っている実用的な制約は、PK / FKのように見えるものだけです。


15
私はこれに丁寧に反対します。データの一貫性が本当に必要な場合、特にビジネスロジックが失敗する場合は、DBの制約が必須です。シナリオを説明している方法では、サイレントフェイルが発生し、間違った割合の失敗によってもたらされた損害がシステム内でさらに伝播されます。それに関するDB制約がある場合、すぐに失敗するため、ビジネスロジック開発者は、破損したデータを許可する代わりに、エラーを早期に確認し、ビジネスロジックシステムにパッチを当てることができます。
マチャド

5
私の理解では、パーセンテージの制約に違反した場合、この例外を処理する必要はありません。そのような違反は、最初にコードにバグがあることを示します(誰かがPercentageクラスのインスタンスの代わりに単純な整数を使用したため、または、検証自体にエラーがあります)、例外的なケース(ネットワーク接続がダウンしているなど)とは対照的です。私にとって、この違反はWebアプリの場合はHTTP 500に、デスクトップアプリの場合はクラッシュにつながり、ログに記録して修正する必要があります。
Arseni Mourzenko

7
@ThomasKilian:いいえ。まったく逆です。特にデータベースの制約があるため、間違ったデータは入りません。ビジネスロジックがコード内で正しい場合、そもそもこれらの制約に違反することはありません。コードにバグが発生した場合、これらの制約はデータベースをスクラップから安全に保ちながら、このバグについて警告します。
Arseni Mourzenko

9
@ThomasKilian:「そもそもそれを正しくする」ことに反対している人はいないと思います。おそらく、経験のある人なら誰でも、システムを設計するのは悪い考えだということを知っていることでしょう。右の最初の時間なしバグやミスがあれば、すべてを取得、これまでシステムのライフタイム中に発生します。DBの制約により、バグや間違いによってデータベースが破損することはありません。
ジャックB

3
@JacquesB私は風車と戦っています。DBにビジネスロジックを配置すると、最初と同じように失敗する可能性があり、同じ方法で保存できません。しかし(!)今では、それが属さないビジネスロジックがあります。DBが腐ったビジネスロジックを保存できると信じることは、単に間違っています。DBのロジックは、ビジネスロジック全体と同じルールに従う必要があります。
qwerty_so

1

最近では、ソフトウェア(Entity Frameworkなど)を使用して、テーブルと列を自動的に生成する人が増えています。その考えは、彼らがSQLスキルを必要とせず、脳の能力を解放することです。

ソフトウェアが「うまくいく」という期待はしばしば非現実的であり、人間がするような制約を作り出しません。

最良の結果を得るには、SQLを使用してテーブルを作成し、制約を手動で追加しますが、これができない場合があります。


もちろん、一部のフレームワークは、PKおよびFK(半)の自動追加をサポートしています。
デビッドアルドリッジ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.