リレーショナルデータベースの整合性の制約-見落とすべきですか?


10

大規模なクエリを高速化し、より良い結果を得るには、リレーショナルデータベースで(FOREIGN KEY制約定義を介して)関係の強制を取り除く方が良いと言うので、私は私が働いている会社の開発者と恒久的に話し合っています。パフォーマンス。

検討中のプラットフォームはMySQL 5.xであり、FOREIGN KEYがセットアップされておらず、関連するテーブルの一部のPRIMARY KEY制約が欠けていても、少なくとも私にとっては妥当ではありません。多分彼らは正しいのですが、私は間違っていますが、私はこの状況について議論するのに十分な議論がありません。

これは3年間、推奨されるアプローチでした。私はこの会社の新人です(わずか1か月)が、製品が「機能する」ため、データベースを拡張するのにためらいがあります。それにもかかわらず、最初に気付いたのは、1ページの読み込みに1分(はい、60秒!)かかっていることです。

現在の状況の背後にある主張の1つは、「非正規化された」データベースは正規化されたデータベースよりも速いということですが、私はそれが本当だとは思いません。

関連するクエリのほとんどにJOIN操作が含まれているため、大量のデータがあると非常に遅くなります(データベースには数百万の行が含まれます)。

通常、「CRUD」操作の処理は、アプリケーションプログラムコードレベルで実装されます。たとえば、FROMからデータを削除するには、次のようにしましょうTableA

  • との行の間に何らかの関係があるかどうかをその場で最初に確認する必要がTableAありますTableB
  • 上記の関係が「検出」された場合、アプリプログラムコードは関連する行の削除を許可しませんが、
  • 何らかの理由でアプリのプログラムコードが失敗した場合、関連する行とテーブルに関係があるかどうかに関係なく、DELETE操作は「成功」します。

質問

議論を深めるために、私が良い、正確で確固とした答えを詳しく説明するのを手伝っていただけませんか?


:たぶん、このようなものは以前に尋ねられた(そして答えられた)かもしれませんが、Googleを使用して何も見つけることができませんでした。


コメントは詳細な議論のためのものではありません。この会話はチャットに移動しました
ポールホワイト9

回答:


12

投稿に記載されているように、リレーショナルデータベース(簡潔にするためにRDB)を作成することが意図されている場合、それがそのように機能すると予想される場合、短い答えは次のとおりです。

  • いいえ、データの整合性の制約を見落としてはいけません

主な目的は、関連データをそのまま管理することであり、非常に貴重な組織資産であり、この目的を達成するための信頼できる方法は、健全な理論でサポートされている技術的手段を採用することです。

したがって、データベースの専門家として、EF Codd博士が提供する最先端の洗練されたリレーショナルモデルメカニズムを利用してビジネスルールを適用し、それらが利用されない場合に最終的に発生する問題を回避できます。

この点について、(a)制約に対する私の全体的な見方と、(b)データベースの問題の状態と問題となっている作業環境についてのいくつかの考慮事項を、次のように共有します。

FOREIGN KEY制約、データ関係、参照整合性

RDBは、関心のあるビジネスコンテキストの特性を高精度で反映する必要があります。これには、ビジネスエキスパートの不可欠な支援を考慮しながら、ベストプラクティスに従い、モデラーまたはデザイナーが主導する詳細な概念レベルの分析が必要です。その分析により、適切なビジネスルールを正確に特定し、定式化する必要があります

したがって、そのようなモデラーが関連性のあるデータの間に相互関係が存在することを識別した場合、データベース管理システム(DBMS)がデータが正確な特性と一致し続けることを保証できるように、対応する論理レベルの制限を構成する必要があります。上記の分析で常に決定されたルール。

議論中のデータベースに関して、関連する相互関係が特定されたと推測できます。これは、アプリケーションプログラムコードを使用して、DBMSファシリティの外部からそれらを強制する手続き的な(そして簡単に回避できる)試みがあるためです(事前関係アプローチ)は、いずれの場合も、データベースの「関係」を調べて、上記の相互関係の全体性を検証する必要があります。

ただし、ご存じのとおり、リレーショナルサイエンスはこの目的のために非常に強力な手段、つまりFOREIGN KEY(FK)制約を規定しているため、これは参照整合性を保護するための最適な手法ではありません。これらの制約は、不要でエラーが発生しやすいアドホック手順に頼らない単一の文であるため、(優れた宣言型アプローチを介して)作成が非常に簡単です。FK制約の実行速度は専門のプログラマーによって高度に最適化されています(そして、主要なプラットフォームベンダーは数十年もの間、FK制約に取り組んできました)。

さらに、RDBは、複数のアプリケーションプログラム(デスクトップ、自動、Web、モバイル、それらの組み合わせ)からアクセスできる独立した(自己保護、自己記述などの)ソフトウェアコンポーネントである必要があるため、これらのアプリのコードと「結合」します。

同様に、重要な組織リソースであるデータは、アプリケーションプログラム、アプリケーションプログラマー、アプリケーション開発プラットフォーム、プログラミングパラダイムよりも長生きする傾向があります。

PRIMARY KEY制約と重複行の影響

-conceptually特定speaking-場合物の種類をビジネス環境で重要であるとみなされている、データベース・モデラーは、確認は、前記(1)は、その関連する特性は、そのプロパティ-を-ie決定しなければならない種類のもののエンティティインスタンスとしてプロトタイプ -つまり、エンティティタイプ-および(2)論理設計の1つ以上のによって統合されたテーブルを介してエンティティタイプを表します

次に、実世界で特定のエンティティタイプの個々のインスタンスを区別することが最も重要であるように、テーブルで囲まれた各行も一意に区別する必要があります。テーブルでKEYが宣言されていない場合、最終的には重複が保持され、まったく同じ値を保持する行が2つ以上ある場合、それらはすべて同じ意味を持ち、すべて同じ事実を表します。

その時点で、複数の理由により重複行は破棄されます。理論的な観点から、設計者は、SQLデータのサブ言語が許可するのと同じように関係のあるテーブルを機能させる(データ操作操作に重要な影響を与える)ために、各行が常に一意であることを確認する必要があります。さらに、情報の観点からすると、複数の行が同じ事実を表す場合、以下に例示するように、それらの記録は不要であるだけでなく有害です。

  • 誰かが特定のテーブルに2つの同じ行を挿入したとします。
  • その後、他の誰かが来て、重複の1つのオカレンスのみを更新します。結果として、もう一方のオカレンスは最新ではなくなりました。
  • 続いて、別の人が、これまで変更されていないオカレンスを更新します。このようにして、両方の複製は、異なる時点で異なる変更を経ています。
  • その後、問題の行によって伝えられる情報を選択することに興味がある場合、その人は2つの異なる「バージョン」を見つけることができます。

この方法では:

  • どの「バージョン」が正しい、信頼できるバージョンと見なすことができますか?
  • どちらが現実の世界を正確に反映していますか?

ご存知のように、この現象は法的にも影響を与える可能性があり、その状況は確かに非常に重要です。

さらに、このような矛盾に対処するために使用する必要がある時間と労力(おそらく、ある種の「更新の同期」を通じて)は、実際に組織に価値をもたらすタスクに専念する必要があります。したがって、データベースの一貫性を維持するために、矛盾する行を保持することは、設計によって回避れるべきです。

PRIMARY KEY(PK)の同定理由である、各制約の宣言をする必要があり、常にデータベース設計者が行うこと。ただし、テーブルには、すべての行を一意に識別する値を保持する複数の列または列の組み合わせがある場合があることにも言及する必要があります。結果として、PK制約(実用的な理由により、理想的にはPRIMARYとして確立される)を設定する以外に、設計者は適用時に1つ以上の代替キー(通常、1つ以上のUNIQUEとNOT NULL制約を介して定義される)も宣言する必要があります。かなり一般的です)。

PKのもう1つの有利な特性は、単一または複合FKに参加するために他のテーブルに「移行」するときに、データ間に存在する関係のカーディナリティ比を強制するのに役立つということです。これらすべては、はい、DBMSによって保証された、シンプルで効率的な宣言型設定によって実現されます。

(現在)CHECK制約と単一行の検証

(現在の)CHECK制約の妥当性を忘れないでください。行の有効な列値のセットを宣言的に制限します(これは単純に見えるかもしれませんが、実際にはリレーショナルDBMSの基本的な機能です)。ビジネスコンテキストのルールが常に正確に反映されていることを確認します。

質問にMySQLタグを付けたとき、残念なことに、そのようなプラットフォームでは、この種の制約の宣言は許可されていますが、その強制は無視されています。、当然のことながら、2004年以降バグとして報告された状況。

この点に関しては、ACID TRANSACTIONS、TRIGGERS、またはDBMS内の他のメソッド(このテーマに関する情報については@ypercubeᵀᴹによるこの回答を参照)などの他の方法でこの要素 を処理する必要があるため、データは一貫している。

アサーション制約:宣言的に追加の複数行および複数テーブルのビジネスルールを設定する

MySQLを含むさまざまなSQL DBMSが何らかの理由でサポートを十分にサポートしていない1つの側面は、明らかにPKとFKを超えて、複数行と複数テーブルの制約を宣言的に有効にすることです。

その一部として、SQL標準には、現在何年も前からのアサーションが含まれています。あなたのビジネス環境のどのルールがその論理レベルの検証アプローチから利益を得るかはわかりませんが、データベース設計者として、1つ以上のASSERTIONでデータを制約することは非常に便利だと思いますが、 DBMS開発者の観点から見ると、この最重要の種類のツールを抽象化の物理レベルで実装することは困難でした。

Oracleのベンダーや開発者 2016年以降、ASSERTIONのサポートを評価しており、それにより、そのDBMSがよりリレーショナルに準拠するようになり、その結果、より堅牢で競争力が高まるようです。(i)コンシューマーがプッシュし続け、(ii)Oracleが実装に成功した場合、(iii)他のDBMSベンダー/コミュニティもそれらを有効にする必要があり、その使用は広がり始めます。確かに、それはデータベース管理の分野では大きな進歩であり、コッド博士が思い描いた最も特徴的なツールの1つであることを、私は個人的にそれがすぐに起こることを期待しています。

データの整合性と意思決定プロセス

上記で説明したように、RDBの最も重要な側面の1つは、RDBが保持するデータの整合性をそれ自体で保証することであり、RDBがモデラーによって宣言された整合性制約に準拠する場合にのみ、整合性が満たされます。

この点で、信頼できる派生テーブル(たとえば、複数のテーブルから列を取得するSELECTステートメントまたはビュー)を作成できるように、整合性が保護されたベーステーブル(DDL構造で確立されたもの)を用意することが義務付けられています。派生テーブルは、必ずしもベーステーブルに関して作成する必要があるためです。

人々が組織的な(そして通常の)意思決定プロセスにおいて主要なツールとして情報を使用することはよく知られています。次に、データベースによって提示された情報が首尾一貫していて正確でない場合、そのような情報に基づく決定は(控えめに言っても)健全ではありません。そのため、RDBは慎重に設計および実装する必要があります。RDBは、ユーザーが十分な根拠のある意思決定を行うのに役立つ信頼できるリソースになるように構築する必要があります。

「非正規化」

悲しいかな、「「非正規化」データベースは正規化データベースよりも速い」というのは広く誤解されていますが、これは論理的、物理的、そして実用的な根拠に反論できる議論でもあります。

まず、非正規化は、ベーステーブルが以前に正規化されていることを必然的に意味します(データベースの抽象化の論理レベルで実行される、正式な科学ベースの手順によって)。

したがって、表が実際には正しく正規化されていると仮定すると、「非正規化」します(これは、単語の正式な意味とは対照的に、広告内の他の表に属し、その一部である列をそれに追加することを含みます)一時的な方法)は、たとえば、1つまたはいくつかの特定のSELECTステートメントの処理を(物理レベルで)高速化するのに役立ちますが、そのような一連のアクションは、同時に、他の多くの関連データの実行を損なう可能性があります操作操作(たとえば、いくつかのINSERT、UPDATE、DELETE、およびSELECTステートメント、または単一または複数のACID TRANSACTIONSで囲まれたそれらの組み合わせ)。

さらに、非正規化(公式であれ非公式であれ)は、データベースの一貫性を低下させる更新/変更の異常引き起こします。これは、複雑でコストがかかり、エラーが発生しやすい手順でこれをすべて回避できる場合に「処理される」可能性がある問題です。始まりです。

正規化および「非正規化」テーブルをサポートする物理レベルの足場

現実の世界で使用されることを意図した論理的な(抽象的な)レイアウト(SQL-DDL設計)は、考慮すべき物理的な(具体的な)影響を明確に保持しています。

このように、「非正規化」テーブルは必然的に「より広い」(追加の列を保持する)ことになります。つまり、その行は必然的に重く(物理レベルのコンポーネントがより多く、より大きくなる)、つまり、基盤となるコンピューティングプロセス(たとえば、ハードドライブまたはメモリに関係するもの)は簡単に遅くなります。

対照的に、当然のことながら「より狭い」(列が少ない)正規化テーブルは、「より速く」動作する「より軽い」要素(より少ない物理的なコンポーネントによって提供される)となり、これに関連する一連のアクションを高速化します。 、例えば、データの書き込みと読み取り。

そのため、(a)関連するテーブルを形式的かつ慎重に正規化し、そのように維持し、(b)データの取得と変更の速度を最適化できる物理レベルのリソースを利用すること(たとえば、慎重かつ効率的なインデックス作成戦略、適切なソフトウェアおよびハードウェアサーバー構成の有効化、ネットワーク帯域幅機能のアップグレードなど。

検討中のデータベースの機能

質問の次の段落は、データ取得操作の速度に関係しています。

[A] s製品が「機能する」場合、データベースを拡張するためにためらいがあります。それにもかかわらず、最初に気付いたのは、1ページの読み込みに1分かかる(はい、60秒です)ことです。

特定のページの読み込みにそれほど時間がかかる場合、システムのユーザーが適切なサービスを受けていないことは明らかです。したがって、それが「機能する」場合でも、その機能はまったく最適ではないようです。つまり、環境全体(データベースとアプリ)をより効率的にするという意図が十分に維持され、非常に建設的な態度を示しています。

そして、科学が間違いなくあなたをサポートし、それゆえあなたがしっかりした姿勢を維持する必要がある場合でも、結局のところ、あなたの雇用者、同僚、そしてあなた自身が組織全体を作るための努力に参加しているので、私は外交的な方法で状況に取り組むことを提案しますもっと成功する。したがって、それはあなたが強調すべき1つの議論です。彼らは他のことを上手く行っている一方で、一般的で特定のデータ管理手法を改善することは、組織的および個人的な成長を生み出すのにかなり役立ちます。

関連するクエリのほとんどにJOIN操作が含まれているため、大量のデータがあると非常に遅くなります(データベースには数百万の行が含まれます)。

JOIN演算子は、データのリレーショナル操作に関連する必須かつ強力な要素であることに注意してください。次に、より堅牢なプラットフォームが比較的高速な実行でサービスを提供しますが、あなたが説明する状況はおそらく、(概念的、論理的、および物理的な抽象化レベルで)非効率的な設計の症状です。だから、私の最初の視力推定は:

  • INDEX設定の改善が必要な場合があります。
  • PKおよびFK列のタイプとサイズの定義を確認する必要があります(PKの考慮事項については@Rick Jamesに完全に同意します。複合KEYは適切な場合に追加されたサロゲートよりもはるかに効率的である傾向があるためです)。
  • さらに(正式な科学ベースの)正規化は、適切な状況(つまり、適切に設計されたRDBで実行される)でJOINが非常に高速に実行されるという事実により、これらの問題を軽減するのに役立つ場合があります。

さらに、はい、@ TommCatt彼の回答で言及しているように、クエリの(論理的)書き換えが(物理的)実行プランを変更して、データの読み取り/書き込みを加速する場合があります。これは、考慮に入れるべき要素です。


1
すばらしい答えです。実装のパフォーマンスを検討するときは、開発者のチームが非常に長い間これらの問題に取り組んできたよりもずっと賢いことを常に思い出します。リレーショナルデータベースは、世界で最も巨大なシステムの中心にあります(FacebookとTwitterでいくつかの明白なものを挙げます)。
Nick Bedford、

9

開発者の基本的な前提は完全に間違っています。外部キーは、システムのDMLのパフォーマンスにわずかに影響します。クエリではまったく使用されないため、パフォーマンスに影響はありません。したがって、開発者は自分が何について話しているのかわからず、アドバイスを受けることを検討すべき最後の人です。

外部キーは、データの整合性を維持する上で重要な役割を果たします。これは、それらを削除することによって得られる小さなパフォーマンスの改善(それが真実であっても)よりもはるかに重要です。

どのような状況で、OLTPデータベースからFKを削除しないでください。

また、非正規化すると、一部のクエリが高速化されることがあります。彼らが言うように、それは依存します。それでも、速度が向上したとしても、データの整合性を維持するために余分な労力をかける価値はありません。

単純なチューニングでは非正規化よりもはるかに速度を改善できない場合は非常にまれです。これは、優れたDBAが(ついに)給与を稼ぐことができる場所です。クエリを調整することもできます。私はかつて30分以上で回答を返すクエリを取り、それを8秒未満で機能させました。データベースへの変更はなく、クエリを書き換えただけです。確かに、これは私の個人的な最高の記録なので、マイレージは異なる場合がありますが、非正規化は最後に試す必要があります。

より複雑なクエリが開発者によって記述されないようにすることもできます。どんなデータが欲しいのか、どんなフォーマットで欲しいのかを尋ねます。次に、それを与えるためのビューを提供します。複雑なクエリはビューになります。その後、開発者は次のように書くだけです。

select <something> from <SomeView> where <whatever>;

私はまた、あなたのデータベースが他の点ではうまく設計されていると想定しています。データベースの設計が不十分であったり、データベースのごく一部であっても、実際には処理が遅くなる可能性があります。私は頻繁に非常に大きなテーブル(それぞれ数十億レコード)を使用して、それらを左右に結合し、ほんの一瞬で答えを期待(および取得)したクエリを使用しました。テーブルのサイズは、クエリの速度を決定するものではありません。

「製品が「上手くいく」ので、データベースを拡張するのにためらいがある」と誰かが言ったとき、私は本当にうんざりしています。この「ためらい」が「私の時計に付いていない」ともっと似ているなら!次に、履歴書の更新を開始することもできます。このような環境から良いものは何も得られず、障害を防止するために変更を行うために何時間もロビー活動を行っていたとしても、将来のすべての障害のせいになります。「今は変更を加えるのに良い時期ではありません」と何度も聞きます。正しい。幸運を。


注意すべき点の1つは、返されるデータの量に基づいて、同じデータに対して異なるクエリが必要になる場合があることです。たとえば、単一の行(またはカウントのみ)を返すクエリは、数千のレコードを返すクエリとは異なる方法で記述した方がよい場合があります。
ジョーW

2

タイトルを変更すると、質問が変わります。 FOREIGN KEYsオプションです。彼らはします:

  • FK INDEXは、テーブルの1つに暗黙的にを作成します。このようなインデックスは手動で追加できます。(このため、FKは必要ありません。)
  • FKは整合性をチェックします。これがFKの名声の主な主張です。アプリケーションで同様のチェックを実行できるため、またはチェックが不要であると判断できるため、FKは必要ありません。そう...
  • 整合性チェックは、パフォーマンスの点でコストがかかります。そのため、処理が遅くなります。(これは通常大したことではありません。)
  • FKは、誰もが望むすべてのことを行うわけではありません。このフォーラムには、「なぜFKはXを実行できないのか」という質問が散らばっています。特に、CHECKオプションは実行されません。
  • FKはCASCADE物事を行うことができます。(個人的には、FKが「正しいこと」をすることを想定せず、制御を維持することを好みます。)

FKの結論:FKを主張する人もいます。一部の製品は、それらがなくても完全に正常に動作します。あなたが決める。

PRIMARY KEYInnoDB を取り除くのは大きな間違いです。一方、サロゲートを削除AUTO_INCREMENTし、1つ(または複数)の列で構成される「自然な」PKを使用することは、多くの場合正しいことです。ここで説明するように、単純で一般的なケースは、many:manyマッピングテーブルです

個人的な経験に基づいて、テーブルの2/3はauto_inc PKの代わりに 'natural'を使用する方が良いと思います。


1
したがって、開発者がたとえば間違いを犯し、DB側に制限がない場合、データが失われるため、ほぼ完璧なアプリケーションに依存しDELETEています。このアプローチは有効ですが、強力なコードと適切なテストが必要ですが、それらにはありませんでした:)
ReynierPM

削除しすぎると、アプリまたはFKで発生する可能性があります。通常、削除が少なすぎることは明らかです。OTOH、私が削除するのが少なすぎてコストに見合うケースを見てきました-物がほとんど削除されない「正規化」を考えてください。余分な未使用の行は実質的に無害です。
リックジェームズ

私が見てきた1高速摂取のためのステージングテーブル-テーブルの上にありませんインデックスに「良い」ケースを。これは非常に一時的であり(したがってInnoDBは必要ありません)、完全に読み取る必要があるだけです(したがって、インデックスは必要ありません)。
リックジェームズ

1
私のとりとめのない共通のテーマに注意してください。単一の答えはありません。万能なものはありません。
リックジェームズ

テーブルが1000行ある場合。パフォーマンスは問題ではありません。テーブルが10億行の長さである場合、正規化、PK、インデックス、FK、UUIDなどに関するすべての「ルール」を精査する必要があります。そうでなければ、dbは溶けます。
リックジェームズ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.