大規模なクエリを高速化し、より良い結果を得るためには、リレーショナルデータベースで(FOREIGN KEY制約定義を介して)リレーションシップの強制を取り除く方が良いと言っているので、私は私が働いている会社の開発者と恒久的に話し合っています。パフォーマンス。
検討中のプラットフォームはMySQL 5.xであり、FOREIGN KEYが設定されておらず、関連するテーブルの一部のPRIMARY KEY制約が欠けていても、少なくとも私にとっては妥当ではありません。多分彼らは正しいと私は間違っていますが、私はこの状況について議論するのに十分な議論がありません。
これは3年間、推奨されるアプローチでした。私はこの会社に新しい(1か月のみ)のですが、この製品は「機能する」ので、データベースを拡張するのにためらいがあります。それにもかかわらず、最初に気付いたのは、1ページの読み込みに1分(はい、60秒!)かかっていることです。
現在の状況の背後にある主張の1つは、「非正規化された」データベースは正規化されたデータベースよりも速いということですが、私はそれが本当だとは思いません。
関連するクエリのほとんどにJOIN操作が含まれているため、大量のデータがあると非常に遅くなります(データベースには数百万の行が含まれます)。
通常、「CRUD」操作の処理は、アプリケーションプログラムコードレベルで実装されます。たとえば、FROMから一部のデータを削除するには、TableA
としましょう。
TableA
とTableB
の行の間に何らかの関係がある場合、最初にオンザフライを確認する必要があります。議論を深めるために、適切で正確かつ確実な答えを詳しく説明するのを手伝っていただけませんか。
注:たぶん、これまでにこのような質問(および回答)があったかもしれませんが、Googleでは何も見つかりませんでした。
あなたの投稿で述べられているように、意図がrelationalデータベース(簡潔にするためにRDB)を作成することであり、したがって、そのように機能すると予想される場合、短い答えは次のとおりです。
主な目的は、関連データをそのまま管理することであり、非常に貴重な組織資産であり、この目的を達成するための信頼できる方法は、健全な理論でサポートされている技術的手段を採用することです。
したがって、データベースの専門家として、最先端のエレガントな リレーショナルモデルDr。EF Codd によって提供されるメカニズムを利用してビジネスルールを適用できます。それらが使用されない場合に最終的に発生する問題を回避します。
この点について、(a)制約に対する私の全体的な見方と、(b)データベースの問題の状態と問題となっている作業環境についてのいくつかの考慮事項について、次のように共有します。
RDBは、関心のあるビジネスコンテキストの特性を高精度で反映する必要があります。これには、ベストプラクティスに従い、不可欠な支援を考慮してモデラーまたはデザイナーが主導する詳細なconceptual-level分析が必要です。ビジネス専門家の。その分析は、適切な識別と定式化を適用可能にしなければなりませんビジネスルール。
したがって、そのようなモデラーが関連性のあるデータ間に相互関係が存在することを識別した場合、データベース管理システム(DBMS)がデータを保証できるように、対応するlogical-level制限を構成する必要があります。上記の分析で決定された正確な特性とルール常時と一貫性を保ちます。
議論中のデータベースに関して、関連する相互関係が特定されたと推測できます。これは、アプリケーションプログラムコード(これにより、DBMS機能の外部からデータベースを強制する手続き的な(そして簡単に回避できる)試みがあるためです。事前関係アプローチ)は、いずれの場合も、データベースの「関係」を調べて、上記の相互関係の全体性を検証する必要があります。
ただし、ご存じのとおり、リレーショナルサイエンスはこの目的のために非常に強力な手段、つまりFOREIGN KEY(FK)制約を規定しているため、参照整合性を保護するための最適な手法ではありません。これらの制約は、単一のsentencesであるため、(優れた宣言的アプローチにより)非常に簡単に作成でき、不要でエラーが発生しやすいアドホックプロシージャに頼る必要がありません。 FK制約の実行速度は、専門のプログラマーによって高度に最適化されている(そして、主要なプラットフォームベンダーが数十年にわたって取り組んでいる)ことに注意することは非常に役立ちます。
さらに、RDBは複数のアプリケーションプログラム(デスクトップ、自動、Web、モバイル、それらの組み合わせ)からアクセスできる独立した(自己保護、自己記述など)ソフトウェアコンポーネントである必要があるため、これらのアプリのコードと「結合」します。
同様に、重要な組織リソースであるデータは、アプリケーションプログラム、アプリケーションプログラマー、アプリケーション開発プラットフォーム、プログラミングパラダイムよりも長生きする傾向があります。
-概念的に言えば-特定の種類がビジネス環境で重要であると見なされた場合、データベースモデラーは、(1)関連する特性(つまり、プロパティ)を決定する必要があります。 種類エンティティインスタンスとしてプロトタイプ —つまり、エンティティタイプ—および(2)1つに統合されるテーブルによってそれを表します論理設計ではcolumns以上。
次に、それがparamountであるように、現実世界の特定のエンティティタイプの個々のinstanceを区別します。各rowで囲まれています- tableも一意に区別する必要があります。テーブルでKEYが宣言されていない場合、最終的には重複が保持され、まったく同じ値を保持する行が2つ以上ある場合、それらはすべて同じ意味を持ち、すべてが同じ事実。
その時点で、複数の理由により重複行は破棄されます。理論的な観点から、設計者は、SQLデータのサブ言語が許可するのと同じくらい関係的に機能するテーブル(データ操作操作に重要な影響を与える)を実現するために、各行が常に一意であることを確認する必要があります。さらに、情報の観点から、複数の行が同じ事実を表す場合、それらの記録は不必要なだけでなく、以下に例示するようにharmfulになります。
この方法では:
ご存知のように、この現象は法的にも影響を与える可能性があり、確かに非常に重要な状況です。
さらに、このような矛盾を処理するために(おそらく、ある種の「更新の同期」によって)時間と労力を費やして、実際に組織に価値をもたらすタスクに専念させる必要があります。したがって、矛盾する行を保持することは避けてください設計によるデータベースの一貫性を維持するため。
これが、主キー(PK)の識別andそれぞれの制約の宣言alwaysがデータベース設計者によって実行される必要がある理由です。ただし、テーブルには、すべての行を一意に識別する値を保持する複数の列または列の組み合わせがある場合があることにも言及する必要があります。その結果、PK制約(実用的な理由によりPRIMARYとして理想的に確立される)を設定する以外に、設計者は適用時に1つ以上の代替キー(通常は1つ以上のUNIQUEとNOT NULL制約を介して定義される)も宣言する必要があります。かなり一般的です)。
PKのもう1つの有利な特性は、単一または複合FKに参加するために他のテーブルに「移行」すると、データ間に存在する関係のカーディナリティ比を強制するのに役立つ可能性があることです。これらすべては、はい、DBMSによって保証された、シンプルで効率的な宣言型の設定によって行われます。
(現在の)CHECK制約の関連性を忘れないでください。行の有効な列値のセットを宣言的に制限します(これは単純に見えるかもしれませんが、実際にはリレーショナルDBMSの基本的な機能です)。ビジネスコンテキストのルールが常に正確に反映されていることを確認します。
質問にMySQLタグを付けたとき、残念なことに、そのようなプラットフォームでは、この種の制約の宣言が許可されていますが、同時に その施行を無視します! 、当然のことながら、 2004年以降バグとして報告されました 。
この点に関して、他の方法、たとえば ACID TRANSACTIONS 、トリガー、またはDBMS内の他のメソッド( この答え を参照)によってこの要素を処理する必要があります @ypercubeᵀᴹ この件についての情報)データが一貫しているように。
MySQLを含むさまざまなSQL DBMSが何らかの理由で十分にサポートしていない場合の1つの側面は、明らかに、PKとFKを超えて、宣言的な方法で複数行と複数テーブルの制約を有効にすることです。
その一部として、SQL標準には、何年も前からのアサーションが含まれています。あなたのビジネス環境のどのルールがその論理レベルの検証アプローチの恩恵を受けるかわかりませんが、データベース設計者として、1つ以上のASSERTIONでデータを制約することは非常に便利だと思いますが、 DBMS開発者の観点から見ると、この最重要の種類のツールを抽象化の物理レベルで実装することは困難でした。
Oracleベンダーや開発者 評価中 アサーションサポートは2016年からサポートされているようです。これにより、DBMSはより関連性が高くなり、その結果、より堅牢で競争力が高まります。 (i)コンシューマがプッシュし続け、(ii)Oracleが実装に成功した場合、(iii)他のDBMSベンダー/コミュニティもそれらを有効にする必要があり、その使用は広がり始めます。確かに、それはデータベース管理の分野では大きな進歩であり、コッド博士が思い描いた最も特徴的なツールの1つであるため、私は個人的にそれがすぐに実現することを期待しています。
上記で説明したように、RDBの最も重要な側面の1つは、それ自体が保持するデータのconsistencyを保証することであり、RDBが宣言した整合性制約にRDBが準拠している場合にのみ、整合性が満たされます。モデラー。
この点で、派生テーブルを作成できるように整合性が保護されたbaseテーブル(DDL構造で確立されたテーブル)を作成することが必須です(例: trustworthyである複数のテーブルから列を取得するSELECTステートメントまたはビュー。これは、派生テーブルをベーステーブルに関して作成する必要があるためです。
人々が組織的(そして通常の)意思決定プロセスにおいて主要なツールとして情報を使用することはよく知られています。次に、データベースによって提示された情報が首尾一貫していて正確でない場合、そのような情報に基づく決定は(控えめに言っても)健全ではありません。そのため、RDBは慎重に設計および実装する必要があります。RDBは、ユーザーが十分な根拠のある意思決定を行うのに役立つ信頼できるリソースになるように構築する必要があります。
悲しいことに、「「非正規化」データベースは正規化データベースよりも高速です」というのは、広く普及している誤解ですが、これは論理的、物理的、および実用的な根拠に反論できる議論でもあります。
まず、非正規化は、ベーステーブルが以前に正規化されていることを意味します(データベースの抽象化の論理レベルで実行される形式、科学ベースの手順により)。 。
したがって、上記の表が実際には正しく正規化されていると仮定すると、それを「非正規化」します(これは、Wordの正式な意味とは対照的に、他の表に属し、その一部である列をそれに追加することを含みます- ad hoc fashion)は、たとえば、1つまたはいくつかの特定のSELECTステートメントの処理を(物理レベルで)高速化するのに役立つ可能性がありますが、そのような一連のアクションは、同時に弱体化する可能性があります他の多くの関連するデータ操作操作(たとえば、いくつかのINSERT、UPDATE、DELETE、およびSELECTステートメント、または単一または複数のACID TRANSACTIONSに囲まれたそれらの組み合わせ)の実行。
さらに、非正規化(正式または非公式)は更新/変更の異常を導入し、データベースの一貫性を低下させます。この問題は、複雑でコストがかかり、エラーが発生しやすい手順で処理される可能性があります。最初からこれらすべてを防ぐことができるとき。
正規化および「非正規化」テーブルをサポートする物理レベルの足場
現実の世界で使用することを目的とした論理的な(抽象的な)レイアウト(SQL-DDL設計)は、考慮する必要のある物理的な(具体的な)影響を明確に保持しています。
このように、「非正規化」テーブルは必然的に「より広い」(追加の列を保持する)ことになります。つまり、その行は必ずheavier(より多くのより大きな物理レベルのコンポーネントが必要)になるため、基礎となるコンピューティングプロセス(たとえば、ハードドライブまたはメモリに関係するプロセス)は、簡単に遅くなる可能性があることに注意してください。
対照的に、当然のことながら「より狭い」(列が少ない)正規化テーブルは、「より速く」機能する(より少ない物理的コンポーネントによって提供される)「より軽い」要素となり、これに関連する一連のアクションを高速化します。 、例えば、データの書き込みと読み取り。
そのため、(a)関連するテーブルを形式的かつ慎重に正規化し、そのままにしておくこと、および(b)データの取得と変更の速度を最適化できる物理レベルのリソースを利用すること(たとえば、慎重かつ効率的なインデックス作成戦略、適切なソフトウェアおよびハードウェアサーバー構成の有効化、ネットワーク帯域幅機能のアップグレードなど。
質問の次の段落は、データ取得操作の速度に関係しています。
[A] s製品が「機能する」場合、データベースを拡張するためにためらいがあります。それにもかかわらず、最初に気付いたのは、1ページの読み込みに1分かかる(はい、60秒です)。
特定のページのロードにそれほど時間がかかる場合、システムのユーザーが適切なサービスを受けていないことは明らかです。したがって、「機能する」場合でも、その機能はまったく最適ではないように思われ、環境全体(データベースとアプリ)をより効率的にするというあなたの意図が十分に維持され、非常に建設的な態度を示しています。
そして、科学が確かにあなたをサポートし、それゆえあなたがしっかりした姿勢を維持する必要がある場合でも、結局のところ、あなたの雇用主、同僚、そしてあなた自身が組織全体を作るための努力に参加しているので、私は外交的な方法で状況に取り組むもっと成功する。したがって、それはあなたが強調すべき1つの議論です。彼らは他のことを上手く行っている一方で、一般的で具体的なデータ管理の実践を改善することは、組織的および個人的な成長を生み出すのにかなり役立ちます。
関連するクエリのほとんどにJOIN操作が含まれているため、大量のデータがあると非常に遅くなります(データベースには数百万の行が含まれます)。
JOIN演算子は、データの関係操作に関連するessentialおよびpowerful要素であることに注意してください。次に、より堅牢なプラットフォームが比較的高速な実行でサービスを提供しますが、あなたが説明する状況はおそらく、(概念的、論理的、および物理的な抽象化レベルで)非効率的な設計の症状です。だから、私の最初の視力推定は:
さらに、はい、 @ TommCatt が 彼の回答 で言及しているように、クエリの(論理的)書き換えが(物理的)実行プランを変更して、データの読み取り/書き込みを高速化します。明らかに考慮に入れるべき要素。
開発者の基本的な前提は完全に間違っています。外部キーは、システムのDMLのパフォーマンスにわずかに影響します。 クエリではまったく使用されませんしたがって、パフォーマンスに影響はありません。したがって、開発者は自分が何について話しているのかわからず、アドバイスを受けることを検討すべき最後の人です。
外部キーは、データの整合性を維持する上で重要な役割を果たします。これは、それらを削除することで得られる小さなパフォーマンス改善よりもはるかに重要です(真実であっても)。
anyの状況では、OLTPデータベースからFKを削除しないでください。
また、非正規化すると、一部のクエリが高速化されることがあります。彼らが言うように、それは依存します。それでも、速度が改善されたとしても、データの整合性を維持するために余分な労力をかける価値はありません。
単純なチューニングでは非正規化よりもはるかに速度を改善できない場合は非常にまれです。これは、優れたDBAが(ついに)給料を稼ぐことができる場所です。クエリを調整することもできます。私はかつて30分以上で回答を返すクエリを取り、それを8秒未満で機能させました。データベースへの変更はなく、クエリを書き直しただけです。確かに、これは私の個人的な最高の記録なので、マイレージは異なる場合がありますが、非正規化は最後に試す必要があります。
より複雑なクエリが開発者によって記述されないようにすることもできます。必要なデータとその形式を尋ねます。次に、データを提供するためのビューを提供します。複雑なクエリはビューになります。その後、開発者は次のように書くだけです。
select <something> from <SomeView> where <whatever>;
私はまた、あなたのデータベースが他の点ではうまく設計されていると想定しています。データベースの設計が不十分であったり、データベースのごく一部であっても、実際には処理が遅くなる可能性があります。私は、非常に大きなテーブル(それぞれ数十億のレコード)を頻繁に使用して、それらを左右に結合し、ほんの一瞬で予想(および取得)した応答を結合しました。テーブルのサイズは、クエリの速度を決定するものではありません。
「製品が「上手くいく」ので、データベースを拡張するのにためらいがある」と誰かが言ったとき、私は本当にうんざりしています。この「ためらい」が「私の時計に付いていない」ともっと似ているなら!次に、履歴書の更新を開始することもできます。そのような環境から良いものは何も得られず、失敗を防ぐために変更を行うために何時間もロビー活動を行ったとしても、将来のすべての失敗のせいにされます。 「今は変更を加えるのに良い時期ではありません」と何度も聞きます。正しい。幸運を。
タイトルを変更すると、質問が変わります。 FOREIGN KEYs
はオプションです。彼らはします:
INDEX
をテーブルの1つに作成します。このようなインデックスは手動で追加できます。 (したがって、FKは必須ではありませんこれには。)CHECK
オプションは機能しません。CASCADE
を実行できます。 (個人的には、FKが「正しいこと」をすることを想定せず、制御を維持することを好みます。)FKの結論:FKを主張する人もいます。一部の製品は、それらがなくても完全に正常に動作します。あなたが決める。
取り除く PRIMARY KEY
InnoDBでは、大きな間違いです。一方、サロゲートを取り除くAUTO_INCREMENT
そして、1つ(またはそれ以上)の列で構成される「自然な」PKを使用することは、rightを行うことです。 here で説明したように、単純で一般的なケースは、many:manyマッピングテーブルです。
個人的な経験に基づいて、テーブルの2/3はauto_inc PKの代わりに 'natural'を使用する方が良いことをお勧めします。