16

各タグがカテゴリにグループ化されていることを除いて、タグ付けのためのデータベース設計のようなものにしようとしています。

たとえば、車両に関するデータベースがあるとします。実際には車両についてあまり知らないとしましょう。そのため、すべての車両にある列を指定することはできません。したがって、車両に情報を「タグ付け」します。

1. manufacture: Mercedes
   model: SLK32 AMG
   convertible: hardtop

2. manufacture: Ford
   model: GT90
   production phase: prototype

3. manufacture: Mazda
   model: MX-5
   convertible: softtop

ご覧のとおり、すべての車が製造元とモデルでタグ付けされていますが、他のカテゴリはすべて一致しているわけではありません。車は各カテゴリの 1 つだけを持つことができることに注意してください。すなわち。車には 1 つのメーカーしかありません。

すべてのメルセデスの検索をサポートするデータベース、またはすべてのメーカーを一覧表示できるデータベースを設計したいと考えています。

私の現在のデザインは次のようなものです:

vehicles
  int vid
  String vin

vehicleTags
  int vid
  int tid

tags
  int tid
  String tag
  int cid

categories
  int cid
  String category

各車のメーカーが 1 つしかない場合を除いて、適切な主キーと外部キーがすべて適切に配置されています。それともできますか?

vehicleTags の複合主キーに外部キー制約を追加できますか? すなわち。複合主キー (vid、tid) を vehicleTags に追加できるのは、同じ vid に対して既に tid が存在しないような行がまだ vehicleTags にない場合に限るような制約を追加できますか?同じシド?

私の推測ではノーです。この問題の解決策は、cid 列を vehicleTags に追加し、新しい複合主キー (vid、cid) を作成することだと思います。次のようになります。

vehicleTags
  int vid
  int cid
  int tid

これにより、自動車に 2 つのメーカーが存在することはなくなりますが、tid が cid にあるという情報を複製しました。

私のスキーマはどうあるべきですか?

Tom は、私のデータベース スキーマにあるこの問題に、以前の質問であるHow do you do many to many table outside join?で気付きました。

編集
例では、製造は実際には車両テーブルの列である必要があることを知っていますが、それができないとしましょう。例はほんの一例です。

4

6 に答える 6

18

これは、 Entity-Attribute-Value設計のさらに別のバリエーションです。

よりわかりやすい EAV テーブルは次のようになります。

CREATE TABLE vehicleEAV (
  vid        INTEGER,
  attr_name  VARCHAR(20),
  attr_value VARCHAR(100),
  PRIMARY KEY (vid, attr_name),
  FOREIGN KEY (vid) REFERENCES vehicles (vid)
);

attr_name混沌を制限するために、定義済みの属性名のルックアップ テーブルを強制的に参照する人もいます。

あなたが行ったことは、EAV テーブルを 3 つのテーブルに広げただけですが、メタデータの順序は改善されていません。

CREATE TABLE vehicleTag (
  vid         INTEGER,
  cid         INTEGER,
  tid         INTEGER,
  PRIMARY KEY (vid, cid),
  FOREIGN KEY (vid) REFERENCES vehicles(vid),
  FOREIGN KEY (cid) REFERENCES categories(cid),
  FOREIGN KEY (tid) REFERENCES tags(tid)
);

CREATE TABLE categories (
  cid        INTEGER PRIMARY KEY,
  category   VARCHAR(20) -- "attr_name"
);

CREATE TABLE tags (
  tid        INTEGER PRIMARY KEY,
  tag        VARCHAR(100) -- "attr_value"
);

EAV 設計を使用する場合は、vehicleTagscategoriesテーブルのみが必要です。

CREATE TABLE vehicleTag (
  vid         INTEGER,
  cid         INTEGER,     -- reference to "attr_name" lookup table
  tag         VARCHAR(100, -- "attr_value"
  PRIMARY KEY (vid, cid),
  FOREIGN KEY (vid) REFERENCES vehicles(vid),
  FOREIGN KEY (cid) REFERENCES categories(cid)
);

ただし、データとメタデータが混在していることに注意してください。データ モデルに特定の制約を適用できなくなります。

  • カテゴリの 1 つを必須にするにはどうすればよいですか (従来の列はNOT NULL制約を使用します)。
  • タグ値の一部を検証するために、SQL データ型をどのように使用できますか? すべてのタグ値に長い文字列を使用しているため、できません。この文字列は、将来必要になるすべてのタグに対して十分な長さですか? わかりません。
  • 一部のタグを許可された値のセットに制限するにはどうすればよいでしょうか (従来のテーブルはルックアップ テーブルへの外部キーを使用します)。これは、「ソフトトップ」と「ソフトトップ」の例です。tagただし、その制約は他のカテゴリの他のすべてのタグ値に適用されるため、列に制約を作成することはできません。エンジンのサイズと塗装色も「ソフトトップ」に効果的に制限します。

SQL データベースは、このモデルではうまく機能しません。正しく理解することは非常に難しく、クエリを実行することは非常に複雑になります。引き続き SQL を使用する場合は、属性ごとに 1 つの列を使用して、従来どおりにテーブルをモデル化することをお勧めします。「サブタイプ」が必要な場合は、サブタイプごとに下位テーブルを定義するか ( Class-Table Inheritance )、またはSingle-Table Inheritanceを使用します。エンティティごとの属性に無制限のバリエーションがある場合は、シリアル化されたLOBを使用します。

この種の流動的で非リレーショナルなデータ モデル用に設計されたもう 1 つのテクノロジは、RDFにデータを格納し、 SPARQLでクエリを実行するセマンティック データベースです。無料のソリューションの 1 つにRDF4J (以前の Sesame) があります。

于 2008-12-17T00:33:16.530 に答える
3

この正確な問題を解決する必要がありました (同じ一般的なドメインとすべて — 自動車部品)。この問題の最善の解決策は、Lucene/Xapian/Ferret/Sphinx または任意のフルテキスト インデクサーを使用することであることがわかりました。SQL が提供できるものよりもはるかに優れたパフォーマンス。

于 2012-10-27T11:43:04.120 に答える
0

この正確な問題を解決する必要がありました (同じ一般的なドメインとすべて — 自動車部品)。この問題の最善の解決策は、Lucene/Xapian/Ferret/Sphinx または任意のフルテキスト インデクサーを使用することであることがわかりました。SQL が提供できるものよりもはるかに優れたパフォーマンス。

最近では、フルテキスト インデクサーを使用せずに、データベースを利用した Web アプリを構築することはほとんどありません。この問題と検索の一般的な問題は、ツールボックスからインデクサーを除外するにはあまりにも頻繁に発生します。

于 2009-04-24T16:46:39.830 に答える
0

あなたの解決策は、単にメーカーの列を車両テーブルに追加することだと思います。これは、すべての車両が持っていることを知っている属性であり (つまり、車両が自然に現れるわけではありません)、これを車両テーブルの列にすることで、車両ごとに 1 つのメーカーしか持たないという問題を解決できます。このアプローチは、すべての車両で共有されることがわかっているすべての属性に適用されます。次に、ユニバーサルではない他の属性のタグ付けシステムを実装できます。

したがって、あなたの例から考えると、車両テーブルは次のようになります。

車両
  ビデオ
  ヴィン
  作る
  モデル
于 2008-12-16T23:31:59.870 に答える
0

1 つの方法は、スキーマを少し再考し、タグ キーを値から正規化することです。

vehicles
  int vid
  string vin

tags
  int tid
  int cid
  string key

categories
  int cid
  string category

vehicleTags
  int vid
  int tid
  string value

必要なのは、 に対する一意の制約だけですvehicleTags(vid, tid)

別の方法として、単純な外部キー以外にも制約を作成する方法があります。データベースによっては、車両タグの一意性を強制するカスタム制約または挿入/更新トリガーを作成できますか?

于 2008-12-16T23:51:52.107 に答える