4

私の雇用主である小規模な事務用品会社は、サプライヤを切り替えようとしています。私は、堅牢なデータベース スキーマを作成するために、サプライヤの電子コンテンツを調べています。私たちの以前のスキーマは、ほとんど何も考えずにまとめられただけであり、破損した一貫性のない情報を含む耐え難いデータ モデルにつながっています。

新しいサプライヤーのデータは古いものよりもはるかに優れていますが、彼らのデータは私が超正規化と呼ぶものです. たとえば、製品カテゴリ構造には、マスター部門、部門、クラス、サブクラス、製品ブロックの 5 つのレベルがあります。さらに、製品ブロックのコンテンツには、製品の長い説明、検索用語、および画像名があります (製品ブロックには製品とすべてのバリエーションが含まれているという考えです。たとえば、特定のペンは黒、青、または赤のインクで提供される場合があります。これらすべてアイテムは本質的に同じものであるため、単一の製品ブロックに適用されます)。私が与えられたデータでは、これは製品ブロックの一意の ID への参照を持つ製品テーブル (「テーブル」と言いますが、データを含むフラット ファイルです) として表されます。

提供されたデータに対応する堅牢なスキーマを考え出そうとしています。比較的すぐにロードする必要があり、提供されたデータは提供されたデータのタイプと一致しないようですサンプル Web サイト ( http://www.iteminfo.com ) でデモを提供しています。いずれにせよ、私は彼らのプレゼンテーション構造を再利用しようとは考えていないので、それは論点ですが、私はサイトを閲覧して物事を構造化する方法についていくつかのアイデアを得ていました.

私が確信が持てないのは、データをこの形式で保持する必要があるかどうか、またはたとえば、自己参照関係を使用してマスター/部門/クラス/サブクラスを単一の「カテゴリ」テーブルに統合し、それを製品ブロック (製品ブロックは「カテゴリ」自体ではなく、特定のカテゴリに関連する製品のグループであるため、個別に保持する必要があります)。現在、製品ブロック テーブルはサブクラス テーブルを参照しているため、これらを統合すると「category_id」に変更されます。

私はおそらく、このデータを Ruby on Rails で利用する e コマース ストアフロントを作成する予定です (少なくとも、それは私の計画です)。考えすぎですが、申し訳ありませんが安全を確保したいと思います。以前のデータは本当に混乱しており、一貫性のない不正確なデータが原因で、会社は何万ドルもの売り上げを失っていました。また、Rails の規則から少し離れて、データベースが堅牢であり、制約が適用されるようにするつもりです (アプリケーション レベルでも行う予定です)。

このような状況にどのように対処しますか?テーブル構造を模倣するフラット ファイルにデータをロードする必要があることに注意してください (どの列がどの参照が設定されているかを示すドキュメントがあります)。それらを現在のように正規化したままにするか、統合する必要があるかを決定しようとしています。各メソッドが Rails を使用してサイトをプログラミングする方法にどのように影響するかを認識する必要があります。統合すると、単一のテーブルに本質的に 4 つの「レベル」のカテゴリが存在するためです。各レベル。サブクラス (製品ブロックに直接リンクする) を除いて、それらは行わないためそれらの下の次のレベルのカテゴリを表示する以外のもの。私は常に、このようなデータを処理するための「最善の」方法を失っています。

4

10 に答える 10

6

私は、非正規データ モデルよりも「超正規化」アプローチを好みます。あなたが言及した自己参照テーブルは、テーブルの数を減らし、いくつかの点で生活を簡素化する可能性がありますが、一般的に、このタイプの関係は扱いにくい場合があります。オブジェクトモデルをこれにマッピングする場合と同様に、階層クエリは面倒になります(そのルートに行くことにした場合)。

いくつかの余分な結合は害を及ぼすことはなく、アプリケーションをより保守しやすくします。結合の数が多すぎてパフォーマンスが低下しない限り、そのままにしておくことを選択します。これらのレベルのテーブルのいずれかに追加機能を追加する必要がある場合の追加ボーナスとして、それらをすべて自己参照テーブルにマージしたため、問題が発生することはありません。

于 2009-02-03T16:10:34.770 に答える
3

親子階層の自己参照テーブル構造に関する批判にはまったく同意しません。リンクリストとツリーは、UIとビジネスレイヤーが通常実装される言語でこのデータを表す自然な方法であるため、リンクリスト構造により、ほとんどの場合、UIとビジネスレイヤーのプログラミングがより簡単で保守しやすくなります。

これらの構造に対するデータ整合性制約を維持することの難しさについての批判は完全に有効ですが、単純な解決策は、より厳しいチェック制約をホストするクロージャーテーブルを使用することです。クロージャーテーブルはトリガーで簡単にメンテナンスできます。

トレードオフは、UIとビジネスレイヤーコードの複雑さを大幅に軽減するために、DB(クロージャーテーブルとトリガー)を少し複雑にすることです。

于 2009-02-03T19:15:43.803 に答える
2

ほとんどの場合、自己参照テーブルは、正規化されたテーブルよりもクエリとパフォーマンスが大幅に低下します。やらないでください。よりエレガントに見えるかもしれませんが、そうではなく、非常に貧弱なデータベース設計手法です。個人的には、あなたが説明した構造は、超正規化されていない私にはうまく聞こえます。適切に正規化されたデータベース (外部キー制約とデフォルト値、トリガー (複雑なルールに必要な場合)、およびデータ検証制約を含む) は、一貫性のある正確なデータを持つ可能性がはるかに高くなります。データベースにルールを適用させることに同意します。これは、ルールが適切な場所で適用されず、人々がルールを簡単に回避できたため、最後のアプリケーションに不適切なデータが含まれていた理由の一部である可能性があります。アプリケーションがそうすべきではない」同様にチェックしてください(たとえば、データベースの挿入に失敗するために無効な日付を送信しても意味がありません)。あなたが再設計しているので、完全に普通の正規化された構造をよりエレガントに見せようとするよりも、必要な制約を設計し、正しいデータ型を選択することに多くの時間と労力を費やします (たとえば、日付を文字列データとして保存しないでください)。

于 2009-02-03T18:05:32.713 に答える
2

私の理解が正しければ、個別のテーブルを取得して、自己参照 FK を持つ単一のテーブルに保持される階層に変換する必要があります。

これは通常、より柔軟なアプローチですが (たとえば、5 番目のレベルを追加する場合)、SQL およびリレーショナル データ モデルは、MS SQL Server の CTE のような新しい構文を使用しても、このようなリンク リストではうまく機能しない傾向があります。確かに、CTE はそれをはるかに改善します。

製品が常に階層の第 4 レベルにある必要があるなど、強制するのは困難でコストがかかる場合があります。

この方法で行うことにした場合は、間違いなく Joe Celko のSQL for Smartiesをチェックしてください。これには、モデリングと SQL の階層の操作に関するセクションが 1 つまたは 2 つあると思います。または、このテーマに特化した彼の本を入手することをお勧めします ( Joe Smarties の SQL における Celko のツリーと階層)。

于 2009-02-03T16:10:01.620 に答える
0

自己参照テーブルを持つオプションだけを考えて、データベースに階層を導入しないことを推奨するすべての人。これは、データベース内の階層をモデル化する唯一の方法ではありません。再帰クエリを使用せずに、より簡単で高速なクエリを提供する別のアプローチを使用することもできます。階層に多数のノード (カテゴリ) があるとします。

Set1 = (Node1 Node2 Node3...)

このセット内のノードは、他のノードまたはネストされたセットを含む別のセットになることもできます。

Node1=(Node2 Node3=(Node4 Node5=(Node6) Node7))

では、それをどのようにモデル化できるでしょうか。各ノードに、含まれるノードの境界を設定する 2 つの属性を持たせましょう。

ノード = { ID: int、最小: int、最大: int }

階層をモデル化するには、それに応じて最小/最大値を割り当てます。

ノード 1 = { ID = 1、最小 = 1、最大 = 10 }ノード
2 = { ID = 2、最小 = 2、最大 = 2 }
ノード 3 = { ID = 3、最小 = 3、最大 = 9 }
ノード 4 = { ID = 4、最小 = 4、最大 = 4 }
ノード 5 = { ID = 5、最小 = 5、最大 = 7 }
ノード 6 = { ID = 6、最小 = 6、最大 = 6 }
ノード 7 = { ID = 7、最小 = 8 、最大 = 8 }

ここで、Set/Node5 の下にあるすべてのノードを照会するには、次のようにします。


s.Id = 5 および s.Min < n.Min および n.Max < s.Max であるNodes as n、Nodes as s から n.* を選択します。

リソースを消費する唯一の操作は、新しいノードを挿入する場合、または階層内でいくつかのノードを移動する場合です。多くのレコードが影響を受けますが、階層自体はあまり頻繁に変更されないため、これは問題ありません。

于 2013-02-28T19:50:44.713 に答える
0

私にとっての本当の問題は、モデルにより適しているのはどれかということです。

タプルとリストを比較するようなものです。

  1. タプルは固定サイズで異種混合です。つまり、「超正規化」されています。
  2. リストは任意のサイズであり、均質です。

タプルが必要な場合はタプルを使用し、リストが必要な場合はリストを使用します。それらは基本的に異なる目的を果たします。

この場合、製品構造はすでに明確に定義されているため (変更される可能性は低いと思います)、「タプル アプローチ」を使用します。リスト (または再帰テーブル パターン) の真の力/使用法は、BOM や系図ツリーなど、任意の深さに拡張する必要がある場合です。

必要に応じて、一部のデータベースで両方のアプローチを使用しています。ただし、すべての ORM (AR については不明) が適切にサポートしているわけではないという、再帰パターンの「隠れたコスト」もあります。最新の DB の多くは、「結合スルー」(Oracle)、階層 ID (SQL Server)、またはその他の再帰パターンをサポートしています。別のアプローチは、セットベースの階層を使用することです (これは通常、トリガー/メンテナンスに依存します)。いずれにせよ、使用されている ORM が再帰クエリを十分にサポートしていない場合は、DB 機能を直接使用すると、手動のクエリ/ビュー生成またはトリガーなどの管理に関して、追加の「コスト」が発生する可能性があります。ファンキーな ORM を使用しない場合、または単に iBatis などのロジック セパレータを使用する場合、この問題は当てはまらない可能性があります。

パフォーマンスに関しては、新しい Oracle または SQL Server (およびその他の可能性が高い) RDBMS では、非常に匹敵するはずなので、私の心配はほとんどありません。

于 2010-11-24T02:04:46.563 に答える
0

あなたのストアフロント(またはあなたが構築しているものは何でも、それについては明確ではありません)は常にこのサプライヤーからのデータを使用するつもりですか? サプライヤーを変更したり、別のサプライヤーを追加したりすることはありますか?

その場合は、ニーズを満たす一般的なスキーマを設計し、ベンダー データをそれにマップします。個人的には、4 つの (明らかに半分役に立たない) レベルのカテゴリ バリアントを維持するよりも、自己参照カテゴリ (階層) テーブルの (信じられないほどマイナーな) '痛み' に苦しみ、来年には 5 番目のレベルが追加されていることがわかります。または、たった3つの製品ラインを導入しました...

于 2010-11-24T01:43:28.933 に答える
0

非正規化しないでください。非正規化によって適切なスキーマ設計を達成しようとすることは、ニューヨークから車で離れてサンフランシスコに行こうとするようなものです。進むべき道は教えてくれません。

あなたの状況では、正規化されたスキーマが何を望んでいるかを把握したいと考えています。これは主にソース スキーマに基づくことができますが、データの機能依存関係 (FD) が何であるかを知る必要があります。ソース スキーマもフラット化されたファイルも、すべての FD を明らかにするとは限りません。

正規化されたスキーマがどのようになるかがわかったら、次に、ニーズを満たすスキーマを設計する方法を理解する必要があります。そのスキーマは完全に正規化されていないので、それで十分です。ただし、フラット化されたファイル内のデータと設計されたスキーマ内のデータとの間の変換をプログラミングする際の困難に備えてください。

あなたの会社の以前のスキーマは、矛盾と不正確さのために数百万ドルの費用がかかったとおっしゃいました。スキーマが正規化されているほど、内部の不整合から保護されます。これにより、不正確さについてより警戒することができます。常に間違っている一貫したデータは、一貫性のないデータと同じくらい誤解を招く可能性があります。

于 2009-02-04T11:33:12.707 に答える