データベース構造を作成するとき、従うべき適切なガイドライン、またはデータベースをどこまで正規化する必要があるかを判断するための適切な方法は何ですか? 正規化されていないデータベースを作成し、プロジェクトの進行に合わせて分割する必要がありますか? 完全に正規化して作成し、パフォーマンスのために必要に応じてテーブルを結合する必要がありますか?
13 に答える
正規化されたデータベースの設計を3番目の正規形まで開始したいとします。ビジネスロジック層を開発するときに、少し非正規化する必要があると判断する場合がありますが、決して3番目の形式を下回ることはありません。常に、第1および第2のフォームに準拠してください。パフォーマンスではなく、コードを単純化するために非正規化する必要があります。そのためにインデックスとストアドプロシージャを使用します:)
「進行中に正規化」しない理由は、データベース設計を変更するたびに、すでに作成したコードを変更する必要があるためです。
いくつかの良い記事があります:
@GrizzlyGuruある賢者は、「痛むまで正規化し、うまくいくまで非正規化する」と言ったことがあります。
それはまだ私を失敗させていません:)
正規化されていない形式で開始することには同意しませんが、私の経験では、正規化されていないデータベースを処理するようにアプリケーションを適応させる方が、正規化されたデータベースよりも簡単です。また、「十分に機能している」状況につながる可能性があるため、(手遅れになるまで)正規化することはできません。
正規化とは、冗長データを排除することを意味します。つまり、非正規化または非正規化データベースは、同じ情報が複数の異なる場所で繰り返されるデータベースです。これは、どこでも同じデータを確実に更新するために、より複雑な update ステートメントを記述する必要があることを意味します。そうしないと、一貫性のないデータが取得され、クエリの出力が現実的でないことを意味します。
これはかなり大きな問題なので、非正規化は害があると言えますが、その逆ではありません。
場合によっては、データベースの特定の部分を非正規化することを意図的に決定することがあります。これは、データを更新する際の余分な作業やデータ破損のリスクよりもメリットが大きいと判断した場合です。たとえば、パフォーマンス上の理由からデータが集約されるデータ ウェアハウスや、最初のエントリの後にデータが更新されないことが多いため、不整合のリスクが軽減されます。
しかし、一般的に、パフォーマンスのために非正規化することにうんざりしています。たとえば、非正規化された結合のパフォーマンス上の利点は、通常、マテリアライズド ビュー(インデックス付きビューとも呼ばれます) を使用することで実現できます。これは、非正規化されたテーブルをクエリするのと同じくらい高速ですが、データの一貫性は保護されます。
Jeff は、彼のブログで彼の哲学のかなり良い概要を公開して います。主なことは、正規化をやりすぎないことです。しかし、取り除かなければならないさらに大きなポイントは、おそらくそれほど重要ではないということです。次の Google を実行している場合を除き、アプリケーションが成長するまで大きな違いに気付かないでしょう。
データベースの正規化は一種の芸術だと思います。
テーブルが多すぎるため、データベースを過度に正規化する必要はありません。単純なオブジェクトのクエリでさえ、必要以上に時間がかかります。
私が従う良い経験則は、何度も繰り返される同じ情報を正規化することです。
たとえば、連絡先管理アプリケーションを作成している場合、Address (Street、City、State、Zip など) を独自のテーブルとして持つことは理にかなっています。
ただし、連絡先がビジネス用または個人用の 2 種類しかない場合、2 種類しかないとわかっている場合、連絡先の種類の表が必要ですか? 私にとってはいいえ。
まず、必要なデータ型を把握することから始めます。Visio のようなモデリング プログラムを使用して支援します。最終的に正規化するため、正規化されていないデータベースから始めたくありません。データが繰り返されると、そのデータが新しいテーブルに取り込まれるのがわかります。データベースが設計されたと感じるまで、そのプロセスについていきます。
テーブルを結合する必要があるかどうかは、テストによってわかります。適切に作成されたクエリは、過度の正規化をカバーできます。
正規化されていないデータベースから始めて、進行するにつれて正規化されたものに移行するのが、通常は最も簡単に開始できると思います。どこまで正常化するかという質問に対して、私の哲学は、痛みが始まるまで正常化することです. 少し大げさなように聞こえるかもしれませんが、一般的には、どこまで進めるかを判断するのに適した方法です。
元のポスターには、データベースがどのような状況で使用されるかは記載されていません。ある時点でフロントエンドのデータを処理するキューブ (OLAP) が必要になるタイプのデータ ウェアハウジング プロジェクトになる場合は、スター スキーマ (ファクト テーブル + ディメンション) を調べるよりも、スター スキーマから始める方が賢明です。正規化。この場合、キンボールの本が大いに役立ちます。
正規化されたデータベースを使用すると、最も柔軟性が高く、メンテナンスが最も簡単になります。私は常に正規化されたデータベースから始めて、対処が必要な実際の問題がある場合にのみ正規化を解除します。
私はこれをコードのパフォーマンスと同じように考えています。つまり、保守可能で柔軟なコードを記述し、パフォーマンスの問題があることがわかっている場合はパフォーマンスのために妥協します。
通常、正規化されたDBから始めて、非常に具体的な問題を解決するために非正規化する方がよいことに同意しますが、おそらく3番目の正規形ではなくBoyce-Codd正規形から始めます。
真実は、「場合による」ということです。それは、次のような多くの要因に依存します。
- コード (ハンドコーディングまたはツール駆動 (ETL パッケージなど))
- プライマリ アプリケーション (トランザクション処理、データ ウェアハウス、レポート)
- データベースのタイプ (MySQL、DB/2、Oracle、Netezza など)
- データベース アーキテクチャ (表形式、列形式)
- DBA 品質 (プロアクティブ、リアクティブ、非アクティブ)
- 期待されるデータ品質 (アプリケーション レベルまたはデータベース レベルでデータ品質を強化しますか?)
可能な限り正規化し、パフォーマンスに絶対に必要な場合にのみ非正規化する必要があることに同意します。マテリアライズド ビューやキャッシング スキームでは、多くの場合、これは必要ありません。
念頭に置いておくべきことは、モデルを正規化することで、不完全な正規化モデルで発生する可能性がある更新異常のリスクを取り除くことができるように、データを制約する方法に関するより多くの情報をデータベースに与えることになるということです。
非正規化すると、更新の異常が発生する可能性があるという事実を受け入れるか、アプリケーション コードで制約の検証を自分で実装する必要があります。これにより、これらの制約を宣言的に定義できる DBMS を使用する利点の多くが失われます。
したがって、コードの品質が同じであると仮定しても、非正規化によって実際にはパフォーマンスが向上するわけではありません。
言及すべきもう 1 つのことは、最近のハードウェアは安価であるため、多くの場合、破損したデータをクリーンアップするための潜在的なコストを受け入れるよりも、問題に追加の処理能力を投入する方が費用対効果が高いということです。
常識を使ってみてください。
また、一部の人は-そして私は彼らに同意する必要があります-あなたがあなた自身があなたのクエリのほとんどで6(魔法の数)テーブルを一緒に結合していることに気付いたなら-関連するものを報告することを除いて-あなたは少し非正規化することを考えるかもしれません。
多くの場合、他のソフトウェアで可能な限り正規化すれば、完了です。
たとえば、オブジェクトリレーショナルマッピングテクノロジを使用すると、さまざまな多対1および多対多の関係に対応する豊富なセマンティクスのセットが得られます。事実上2つの主キーを持つ結合テーブルを提供する内部。比較的まれですが、真の正規化により、3つ以上の主キーとの関係が得られることがよくあります。このような場合、さまざまなDBの異常を回避するために、O / Rに固執し、独自のコードをロールすることを好みます。