より良いデータベース設計は何ですか:テーブルを増やすか、列を増やすか?[閉まっている]

StackOverflow https://stackoverflow.com/questions/59482

質問

元同僚は、テーブル数が少なく、列数が多いデータベースよりも、列数が少ないテーブルが多いデータベースの方が優れていると主張しました。たとえば、名前、住所、都市、州、郵便番号などを含む顧客テーブルではなく。列には、名前テーブル、住所テーブル、市区町村テーブルなどが含まれます。

彼は、この設計の方が効率的で柔軟だと主張しました。おそらく、そのほうが柔軟性があるかもしれませんが、私にはその効率についてコメントする資格がありません。たとえ効率が向上したとしても、追加された複雑さの方が利点を上回る可能性があると思います。

では、より多くの列を含む少数のテーブルよりも、より少ない列を含むより多くのテーブルに大きな利点があるのでしょうか?

役に立ちましたか?

解決

私には、データベースを設計するときに従うかなり単純な経験則がいくつかあります。これは、このような意思決定を行うのに役立つと思います。

  1. 正規化を支持します。非正規化は、必要なトレードオフをすべて伴う最適化の一形態であるため、次のような方法で取り組む必要があります。 ヤグニ 態度。
  2. データベースを参照するクライアント コードがスキーマから十分に分離されていることを確認し、再加工してもクライアントの大規模な再設計が必要にならないようにしてください。
  3. 非正規化によってパフォーマンスやクエリの複雑さが明らかに向上する場合は、非正規化を恐れる必要はありません。
  4. スキーマのコアを非正規化するのではなく、ビューまたはダウンストリーム テーブルを使用して非正規化を実装します。 データ量と使用シナリオが許容する場合.

これらのルールの通常の結果は、冗長性の排除に重点を置いて、初期設計では列よりもテーブルが優先されることになります。プロジェクトが進行し、非正規化ポイントが特定されると、全体の構造は、他の貴重な利点と引き換えに、限られた冗長性とカラムの増加を犠牲にしてバランスをとる方向に進化します。

他のヒント

私はテーブルを増やすことを支持しますが、それはある時点までです。この例を使用すると、ユーザーの情報を USERS と ADDRESS という 2 つのテーブルに分割すると、ユーザーごとに複数のアドレスを柔軟に持つことができます。これの明らかな応用例の 1 つは、請求先住所と配送先住所が別々にあるユーザーです。

個別の CITY テーブルを使用することを支持する理由は、各都市の名前を 1 回保存するだけで済み、必要なときにそれを参照すればよいということです。そうすることで重複は減りますが、この例ではやりすぎだと思います。スペース効率は向上するかもしれませんが、データベースからデータを選択するときに結合で代償を支払うことになります。

テーブル/列に関する質問ではなく、正規化に関する質問のように思えます。状況によっては、高度な 正規化 (この場合は「テーブルを増やす」) は適切でクリーンですが、関連する結果を得るには通常、多数の JOIN が必要になります。データセットが十分に大きい場合、パフォーマンスが低下する可能性があります。

ジェフは書きました StackOverflow の設計に関して少し説明します。Jeff のリンク先の投稿も参照してください。 だれおばさんじょ.

完全に正規化された設計 (つまり、「より多くのテーブル」) は、より柔軟で保守が容易で、データの重複を回避できるため、データの整合性を強制するのがはるかに簡単になります。

これらは正常化する強力な理由です。最初に正規化してから非正規化のみを行うことを選択します 特定の テーブル パフォーマンスが問題になっていることに気づきました。

私の経験では、現実世界では、たとえ非常に大規模なデータセットであっても、非正規化が必要な点には到達しません。

それはデータベースの種類によって異なります。たとえば、MS SQL Server は狭いテーブルを好む傾向があります。これは、より「正規化された」アプローチでもあります。他のエンジンでは逆の方が好まれるかもしれません。メインフレームはそのカテゴリに分類される傾向があります。

各テーブルには、主キーによって一意に識別されるエンティティに関連する列のみを含める必要があります。データベース内のすべての列がすべて同じエンティティの属性である場合、すべての列を含むテーブルが 1 つだけ必要になります。

ただし、列のいずれかが null である可能性がある場合は、正規化するために、メイン テーブルへの外部キーを使用して、null 許容の各列を独自のテーブルに配置する必要があります。これは一般的なシナリオであるため、よりクリーンなデザインを実現するには、既存のテーブルに列よりも多くのテーブルを追加する可能性があります。また、これらのオプションの属性を独自のテーブルに追加すると、NULL を許可する必要がなくなり、NULL 関連の多くの問題を回避できます。

これら 1 対 1 の関係が将来 1 対多または多対多になる可能性がある場合、複数テーブル データベースはより柔軟になります。たとえば、一部の顧客の複数の住所を保存する必要がある場合、顧客テーブルと住所テーブルがあれば非常に簡単です。住所の一部を複製する必要があるが、他の部分は複製しない必要があるという状況は実際には考えられないので、住所、都市、州、郵便番号のテーブルを個別に作成するのは少しやりすぎかもしれません。

他のものと同様に:場合によります。

列数とテーブル数に関して厳密な規則はありません。

顧客が複数のアドレスを持つ必要がある場合は、そのための別のテーブルが合理的です。City 列を独自のテーブルに正規化する正当な理由がある場合は、それも可能ですが、これは (通常は) 自由形式フィールドであるため、これまで見たことがありません。

テーブルヘビーで正規化されたデザインは、スペースの点で効率的で、見た目は「教科書通り」ですが、非常に複雑になる可能性があります。顧客の名前と住所を取得するために 12 回の結合を実行する必要があるまでは、見た目は問題ありません。これらのデザインはそうではありません 自動的に 最も重要なパフォーマンスの点で素晴​​らしいです:クエリ。

可能であれば複雑さを避けてください。たとえば、顧客が 2 つの住所しか持てない場合 (任意の数ではなく)、それらすべてを 1 つのテーブル (CustomerID、Name、ShipToAddress、BillingAddress、ShipToCity、BillingCity など) に保持するのが合理的かもしれません。

ジェフの投稿はこちら 話題になっている。

テーブルの列数が少ないことには利点がありますが、上記のシナリオを見て、次の質問に答える必要もあります。

顧客は複数の住所を持つことができますか?そうでない場合は、アドレス用の別のテーブルは必要ありません。その場合、テーブルに列を追加するのが難しくなる場合でも、必要に応じてアドレスを簡単に追加できるため、別のテーブルが役に立ちます。

最初のステップとして正規化を検討するので、都市、郡、州、国は別の列として使用する方がよいでしょう...SQL 言語の能力と最新の DBMS-es を組み合わせることで、他の非正規化ビューで表示する必要がある場合に、後でデータをグループ化することができます。

システムの開発中に、改善点があると判断した場合は、一部の部分を「非正規化」することを検討するかもしれません。

この場合はバランスが取れていると思います。テーブルに列を配置することが意味がある場合は、テーブルに配置しますが、そうでない場合は、配置しないでください。同僚のアプローチはデータベースの正規化に間違いなく役立ちますが、必要な情報を取得するために 50 のテーブルを結合する必要がある場合には、あまり役に立たない可能性があります。

私の答えは、最善の判断をしてください、ということだと思います。

これには多くの側面がありますが、アプリケーション効率の観点から見ると、モート テーブルの方が効率的な場合があります。多数の列を含むテーブルがいくつかある場合、データベースが操作を実行するたびにロックが発生する可能性があり、ロックの間、より多くのデータが使用できなくなります。ロックがページとテーブル (できればテーブルではないことを願っています:) にエスカレートすると、これによってシステムの速度がどのように低下​​するかがわかります。

ふーむ。

それはウォッシュであり、特定のデザインモデルに依存すると思います。独自のテーブルに複数のフィールドを持つエンティティ、またはアプリケーションの要件の変化に応じて構成が変わる可能性があるエンティティを確実に除外します (たとえば、住所は非常に多くのフィールドがあるため、とにかく除外しますが、した 特に 形式が異なる可能性がある外国の住所を処理する必要があると思われる場合は、そうしてください。電話番号も同様です)。

とはいえ、それが機能するようになったら、パフォーマンスに注目してください。大規模でコストのかかる結合を実行する必要があるエンティティをスピンアウトした場合は、そのテーブルを元のテーブルにスピンバックすることがより適切な設計上の決定になる可能性があります。

には大きなメリットがあります クエリ できるだけ少ない列を使用します。ただし、テーブル自体には大きな数を含めることができます。 ジェフ これに関しても何か言ってます。

基本的に、クエリを実行するときは、必要以上のものを要求しないようにしてください。クエリのパフォーマンスは、要求する列の数に直接関係します。

決定を下す前に、保存しているデータの種類を確認する必要があると思います。アドレス テーブルがあることは素晴らしいことですが、それは複数の人が同じアドレスを共有する可能性が高い場合に限られます。全員が異なるアドレスを持っている場合、そのデータを別のテーブルに保持すると、不必要な結合が発生するだけです。

都市自体がアプリケーションで重要なエンティティでない限り、都市テーブルを使用する利点はわかりません。または、ユーザーが利用できる都市の数を制限したい場合。

要するに、このような決定は、効率性を追求する前にアプリケーション自体を考慮する必要があるということです。IMO。

データベースを設計するときは、アプリケーションのニーズではなく、データの意味にできるだけ近づけるべきです。

優れたデータベース設計は、変更せずに 20 年以上持続する必要があります。

顧客は複数の住所を持つ可能性がありますが、それが現実です。最初のリリースではアプリケーションが 1 つのアドレスに制限されると判断した場合は、データではなくアプリケーションの設計が問題になります。

クエリを簡略化したい場合は、複数の列ではなく複数のテーブルを用意し、ビューを使用することをお勧めします。

ほとんどの場合、データベースでパフォーマンスの問題が発生しますが、それはクエリの複雑さではなく、ネットワーク パフォーマンス (結果が 1 行のチェーン クエリ、不要な列のフェッチなど) に関するものです。

まず、テーブルを正規化します。これにより、冗長なデータが回避され、スキャンするデータの行が減り、クエリが改善されます。その後、結合している正規化テーブルによってクエリの処理に時間がかかる箇所 (コストのかかる結合句) に遭遇した場合は、より適切な場所で非正規化を行います。

非常に多くの刺激的で適切な根拠に基づいた回答を見ることができてうれしいです。

私の答えは(残念ながら)こうなります。場合によります。

2 つのケース:* 長年使用するデータモデルを作成し、将来的に多くの変更を加える必要がある場合:より多くのテーブルとより少ない行、そしてかなり厳密な正規化を目指してください。* 他の場合には、テーブルのない行を増やすか、テーブルを減らして行を増やすかを選択できます。特にこのテーマに比較的慣れていない人にとって、この最後のアプローチはより直観的で理解しやすいものとなるでしょう。

オブジェクト指向アプローチと他のオプションのどちらを選択する場合にも同じことが当てはまります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top