6

注: この質問は、明確にするために 11/19/12 に言い換えられました。通常、ここではあまり問題はありませんが、クライアント サイト用の新しい製品システムの設計に苦労しています。私たちは、各クライアントが自分の顧客に販売できる一連の製品を提供します。新製品はいつでも追加できますが、すべて次の形式に従っています。

  1. カテゴリー
  2. タイプ
  3. 製品

前の構造を使用して実際の例を示すには、次のようにします。

  • 野球用品
    • 手袋
      • ローリングス
      • ナイキ
      • ミズノ
    • コウモリ
      • イーストン
      • ルイビル・スラッガー
  • サッカー用品
      • ナイキ
      • リーボック
      • アディダス
    • フットボール
      • ナイキ
      • 苗木
      • ウィルソン
  • ....

上記のリストは明らかに続いており、はるかに大きくなる可能性がありますが、全体的なアイデアを示しています.

現在、特定のクライアントが販売できる製品の種類を、次のように単一のフラット形式のテーブルに格納しています。

ID  | clientID | categoryID | typeID | productID | customURL
=============================================================
1   |  111     |    1       |   1    |   1       | 1111
2   |  111     |    1       |   2    |   2       | 2222
3   |  111     |    1       |   2    |   3       | 3333
4   |  111     |    2       |   3    |   4       | 4444
5   |  222     |    1       |   1    |   1       | 5555
6   |  222     |    2       |   3    |   4       | 6666
  • 上記の例では、カテゴリ 1 を「野球用品」、カテゴリ 2 を「サッカー用品」にすることができます。
  • 対応する categoryID、typeID、および productID の名前は、正規化を維持するために、FK 関係 (innodb) を持つ 3 つの別々のテーブルに格納されます。
  • タイプは、第 2 レベルのアイテム (手袋、バット、靴、フットボールなど) を指します。これらの数値が交差することはありません (つまり、たとえ一般的な製品が同じであっても、同じ typeID が存在することはあり得ません (野球用の靴は、サッカー用の靴とは別の ID を持っています)。
  • このテーブルでは、clientID 1 は 4 つの製品 (カテゴリ 1 に 3 つ、カテゴリ 2 に 1 つ) を販売できます。ClientID 2 は、各カテゴリに 1 つずつ、合計 2 つの製品を販売できます。

私はテーブルを構造化したままにしておく傾向がありますが、他の設計では、正規化のためにテーブルを分離した可能性があることを知っています。ここに当てはまるかどうかはわかりません. それらを分割すると、次のように、これが 1 つのテーブルから 4 つ以上になることがわかります。

製品提供表

ID  | clientID | productID | customURL
======================================
1   |  111     | 1       | 1111
2   |  111     | 2       | 2222
3   |  111     | 3       | 3333
4   |  111     | 4       | 4444
5   |  222     | 1       | 5555
6   |  222     | 4       | 6666

製品定義テーブル

ID  | productID | typeID | productName
======================================
1   |  1        |    1   | rawlings glove
2   |  2        |    2   | product2
3   |  3        |    2   | product3
4   |  4        |    3   | product4

タイプ定義テーブル

ID  | typeID | categoryID | typeName
=====================================
1   |  1     |    1       | Gloves
2   |  2     |    1       | Bats
3   |  3     |    2       | Shoes
4   |  4     |    2       | Footballs

カテゴリ定義テーブル

ID  | categoryID | catName
=============================
1   |  1         | Baseball Equipment
2   |  2         | Football Equipment

私はこれを考えすぎていますか?両方の方法で最終的な解決策が同じように得られませんか?

4

4 に答える 4

9

正規化の目的と利点は、異常なデータの入力が困難になる (理想的には不可能になる) ことです。

たとえば、図 1 で、typeid 3 と categoryid 1 の行を誤って格納するのを防ぐにはどうすればよいでしょうか? 絶対に完璧なアプリケーション コードを書くこと以外には何もありません。

ただし、単一テーブル アプローチを使用し、typeid 3 の親カテゴリを変更する必要がある場合は、変更を反映するために何百万もの場所でデータを変更する必要があります。これは、そのクリーンアップの実行中にテーブルをロックすることを意味します。そうしないと、新しいデータが同時に挿入される可能性があります。

正規化は情報の冗長な格納を排除するのに役立ち、すべての個別のファクト (たとえば、typeid 3 が categoryid 2 に属する) が一度だけ格納される場合、アトミックに変更を加えることが容易になり、その行へのすべての参照の意味が自動的に変更されます。

あなたはより多くの結合が必要であることは正しいですが、あなたがやっているようにあらゆる場所で疑似キーを使用する場合に限ります. 必ずしもそうする必要はありません。代わりに自然キーを使用できます。それらへの参照はカスケード外部キーで宣言されるため、ルックアップ テーブルの変更により、参照テーブルも自動的に更新されます。

確かに、正規化のルールは、疑似鍵の使用を義務付けていません。これらのルールは、それらについて何も言いません。


あなたのコメントについて: pseudokey、またはsurrogate keyは、行を識別するために使用される「id」列です。通常、値は、同時トランザクションが行を挿入できるようにしながら、一意性を保証する自動インクリメント メカニズムによって割り当てられます。id の値は、それが識別する行に関しては意味がありません。


以下は、テーブルが通常の形式でどのように見えるかを示していますが、代理キーはありません。

製品提供表

client | product        | customURL
===================================
Smith  | Rawlings Glove | 1111
Smith  | Product 2      | 2222
Smith  | Product 3      | 3333
Smith  | Product 4      | 4444
Jones  | Rawlings Glove | 5555
Jones  | Product 4      | 6666

製品定義テーブル

product        | type
=======================
Rawlings Glove | Gloves
Product 2      | Bats
Product 3      | Bats
Product 4      | Shoes

タイプ定義テーブル

type      | category
==============================
Gloves    | Baseball Equipment
Bats      | Baseball Equipment
Shoes     | Football Equipment
Footballs | Football Equipment

カテゴリ定義テーブル

category
==================
Baseball Equipment
Football Equipment

主キー列のデータ型として非整数を使用することは、リレーショナル データベースの設計と正規化に完全に準拠しているため、外部キーは他のテーブルからそれらを参照します。

パフォーマンスや簡潔さのために、または他の列の値を自由に変更できるようにするために、代理キーを使用する正当な理由があります。ただし、正規化では代理キーの使用は必須ではありません。

于 2012-11-19T22:43:11.937 に答える
1

とにかく、フラットアプローチではカテゴリ名とタイプ名(およびおそらく他の属性)の個別のルックアップテーブルを維持する必要があるため、正規化されたアプローチを使用します。

次のようなテーブルを使用して、カテゴリとタイプを一般的なツリー構造に変更することを検討してください。

 create table product_hierarchy(
    id integer primary key,
    name character,
    parent_id references product_hierarchy)

...クライアントに階層をさらに深くする柔軟性を与えるためです。

于 2012-11-19T22:38:16.450 に答える
1

直接の質問に対処するには:

私はこれを考えすぎていますか?

アプリケーションの大きさと、データの保存に使用しているエンジンによって異なります。それをMySQLテーブルに入れることを計画しているので、あなたの考えは非常に適切です.

両方の方法で最終的な解決策が同じように得られませんか?

そうですね、ウィキペディアを引用すると、

データベースの正規化は、冗長性と依存性を最小限に抑えるために、リレーショナル データベースのフィールドとテーブルを編成するプロセスです。通常、正規化では、大きなテーブルを小さな (冗長性の少ない) テーブルに分割し、それらの間の関係を定義します。目的は、データを分離して、フィールドの追加、削除、および変更を 1 つのテーブルだけで行い、定義されたリレーションシップを介してデータベースの残りの部分に伝播できるようにすることです。

あなたが説明した構造にデータを分割すると (ちなみに、これには同意します)、データを最も簡単に維持できます。カテゴリとタイプのデータを「提供される製品」と同じテーブルに保持すると、多くの冗長データが作成されます。確かに、どこでそのデータを更新する必要があるか想像もつきませんが、そうすると、多くのレコードを更新する必要があります。提案された構造では、更新されるレコードの数は最小限です。

于 2012-11-19T22:39:29.367 に答える
0

最初のアプローチでは、各カテゴリ、タイプ、および製品 ID の名前列を忘れていました。この情報を追加すると機能しますが、他のアプローチは既に機能しているようです。4 つの異なるテーブルを使用すると、より多くのスペースが確保されます。

于 2012-11-19T22:31:13.873 に答える