エンティティ属性値データベースと厳密なリレーショナルモデルのeコマース


136

EAV / CRデータベースモデルが悪いと言っても安全です。それは言った、

質問:実行時に変更できるeコマース製品を説明する属性の「クラス」を処理するには、どのデータベースモデル、手法、またはパターンを使用する必要がありますか?

優れたeコマースデータベースでは、オプションのクラスを保存します(テレビの解像度には各テレビの解像度がありますが、次の製品はテレビではなく、「テレビの解像度」がない場合があります)。それらをどのように保存し、効率的に検索し、ユーザーが製品を説明する変数フィールドを使用して製品タイプをセットアップできるようにしますか?顧客が通常はコンソールの奥行きに基づいてテレビを検索することが検索エンジンで判明した場合は、コンソールの奥行きをフィールドに追加し、実行時にテレビ製品のタイプごとに1つの奥行きを追加できます。

優れたeコマースアプリには、一連の製品を表示した後、「ドリルダウン」サイドメニューに「TV解像度」をヘッダーとして表示できるという優れた共通機能があり、上位5つの最も一般的なTV解像度がセットが見つかりました。いずれかをクリックすると、その解像度のテレビのみが表示され、サイドメニューで他のカテゴリを選択してさらにドリルダウンできます。これらのオプションは、実行時に追加される動的な製品属性です。

さらなる議論:

要するに、インターネットやモデルの説明に、次の設定を「劇的に」修正する可能性のあるリンクはありますか? カテゴリテーブルを提案してくれたNoel Kennedyに感謝しますが、必要性はそれよりも大きいかもしれません。以下に別の方法で説明し、重要性を強調します。問題を解決するために視点を修正する必要があるかもしれませんし、EAV / CRに深く入り込む必要があるかもしれません。

EAV / CRモデルに対する肯定的な反応が大好きです。私の仲間の開発者全員が、ジェフリーケンプが以下に触れた内容を述べています。問題は:

  • エンティティは属性を毎週追加および削除します
    (検索キーワードは将来の属性を指示します)
  • 新しいエンティティが毎週到着します
    (製品はパーツから組み立てられます)
  • 古いエンティティは毎週消えます
    (アーカイブされ、人気が低く、季節的)

顧客は2つの理由で製品に属性を追加したいと考えています。

  • 部門/キーワード検索/類似製品間の比較表
  • チェックアウト前の消費者向け製品構成

属性には、キーワード検索だけでなく、重要性がなければなりません。「ホイップクリームのフロスティング」があるすべてのケーキを比較したい場合は、ケーキをクリックし、誕生日のテーマをクリックし、ホイップクリームのフロスティングをクリックし、ホイップクリームのフロスティングがあることを知っている興味深いケーキをすべてチェックします。これはケーキに固有のものではなく、単なる例です。


自分自身を参照する外部キーを持つ「カテゴリ」テーブルを作成できないのはなぜですか?
ノエルケネディ

29
EAVデータベースモデルは一部のアプリケーションに適しているため、悪いと言っても安全でも正確でもありません。
spencer7593

Entity Framework 4のように親から継承して、さまざまなプロパティでさまざまなオブジェクトを装飾するとどうなるでしょうか。それらのオブジェクトをどのように永続化しますか?
ザカリースコット

1
EAVの極端なバージョンに基づくシステムでの1人のコンサルタントの経験についてのこの優れた記事に戻って指摘します。それを読んで!simple-talk.com/opinion/opinion-pieces/bad-carma
ジェフリーケンプ

1
EAVは非常に実行可能なデータベースモデルです。私はあなたと同じような問題に取り組んでおり、解決策はEAVです。次の記事をお勧めします。sqlblog.com
Sandor

回答:


75

考えられる一般的な長所と短所がいくつかあります。一方が他方よりも優れている状況があります。

オプション1、EAVモデル:

  • プロ:シンプルなアプリケーションを設計および開発する時間を短縮
  • プロ:新しいエンティティを簡単に追加できます(ユーザーが追加することもできますか?)
  • プロ:「汎用」インターフェースコンポーネント
  • 短所:単純なデータ型の検証に必要な複雑なコード
  • 短所:単純なレポートのためのはるかに複雑なSQL
  • 欠点:複雑なレポートがほぼ不可能になる
  • 短所:大きなデータセットのパフォーマンスが低い

オプション2、各エンティティを個別にモデリングする:

  • 欠点:要件の収集と設計に必要な時間の増加
  • 欠点:新しいエンティティは、専門家がモデル化および設計する必要があります
  • 欠点:各エンティティのカスタムインターフェイスコンポーネント
  • プロ:データ型の制約と実装が簡単な検証
  • メリット:SQLは記述、理解、デバッグが簡単
  • プロ:最も複雑なレポートでも比較的シンプルです
  • プロ:大規模なデータセットの最高のパフォーマンス

オプション3、組み合わせ(モデルエンティティは「適切に」ですが、一部/すべてのエンティティのカスタム属性に「拡張」を追加します)

  • 賛成/反対:要件の収集と設計に必要な時間はオプション1よりも長くなりますが、オプション2ほどではありません*
  • 欠点:新しいエンティティは、専門家がモデル化および設計する必要があります
  • プロ:新しい属性は後で簡単に追加できます
  • 欠点:単純なデータ型の検証に必要な複雑なコード(カスタム属性用)
  • 短所:カスタムインターフェースコンポーネントがまだ必要ですが、カスタムインターフェースコンポーネントの一般的なコンポーネントが可能です
  • 短所:カスタム属性がレポートに含まれるとすぐにSQLが複雑になる
  • 欠点:カスタム属性で検索またはレポートする必要がない限り、一般的に良好なパフォーマンス

* オプション3が設計段階で時間を節約できるかどうかはわかりません。

個人的には、オプション2に頼り、可能な限りEAVを避けます。ただし、一部のシナリオでは、ユーザーはEAVに付属する柔軟性を必要とします。しかし、これには大きなコストが伴います。


1〜nのテキスト値のインデックスを持つ単一のテーブルがある場合は、C#(ram内)で必要なものにマップします。それでもEAVのように機能しますが、「一致」はドメインモデルになります。シリアル化のようなものですが、インデックス付きテキストフィールドでSQL選択を使用できます。レコードごとの複数選択はありません。すべての「コスト」はRAMで発生します。
ザカリースコット

1
@Zim、それはオプション3によく似ています。各行には1-nの余分な「汎用」列があり、それらに格納されたデータはアプリケーションレベルで解釈されます。1つのレコードのすべてのデータを1か所に置くというパフォーマンス上の利点があります。ただし、これらの列に関するメタデータはどこかに保存する必要があり、これはコストが忍び寄る場所です。確かに、メタデータをRAMにキャッシュできますが、アプリケーションコードでドメインを直接モデル化するよりもコストがかかります。確かに本格的なEAVモデルよりも優れています!
ジェフリーケンプ

1
+10000すばらしい答え。今日では、人々はデータベースの設計と要件の収集を控えめにしています。彼らはむしろ、何百倍ものコードを書いて、良いデザインを作るのに時間がかかるのです。
TulainsCórdova14年

あなたは必要としないより多くのあなたが唯一のオプション1のstuctureを供給しているとリレーショナルインターフェイスは、その構造を記述するメタデータから一般的なものであればEAVオプション(1)より、リレーショナルオプション(2)の設計を。これにより、オプション2の短所がすべて削除されます。ただし、唯一の実際のCon:DDLを忘れていると、テーブルの管理が非常に遅くなる可能性があります。
philipxy

こんにちは@philipxy、「もっとデザインする」とは言いませんでした。EAVの存在理由は、(おそらく)システム設計者がモデルの設計に費やす時間を減らし、後でこの設計作業を「ユーザー」に任せることができるということです(この専門的な設計の欠如は、オプション1にリストされた短所につながります)。 。EAVがデザイナーに節約をもたらさない場合、手元にないEAVを拒否するために火に燃料を追加するだけです。また、DDLが「遅すぎる」ことには同意しません。DDLはめったに必要とされない(つまり、モデルのエラーを修正する、または新しい機能を実装する)ため、そのパフォーマンスは比較的重要ではないはずです。
ジェフリーケンプ

63

EAV / CRデータベースモデルが悪いと言っても安全です。

いいえ、ちがいます。リレーショナルデータベースの非効率的な使用法であるだけです。純粋なキー/値ストアは、このモデルでうまく機能します。

さて、あなたの本当の質問へ:さまざまな属性を保存して検索可能に保つ方法は?

EAVを使用するだけです。あなたの場合、それは単一の余分なテーブルになります。属性名と値の両方にインデックスを付けると、ほとんどのRDBMは属性名の繰り返しにprefix-compressionを使用して、本当に高速でコンパクトになります。

EAV / CRを使用して「実際の」フィールドを置き換えると、醜くなります。すべてのツールと同様に、ツールの使いすぎは「悪い」ものであり、悪いイメージを与えます。


だから問題は私が私のカテゴリーの1つに15の追加フィールドを持っていることです、そしてeavモデルではそれは16の結合+メインテーブルを必要とするので、製品を検索するために16の左結合を作ります(そして顧客が望むなら16を持っています)人々が中古品を販売するためのウェブサイト)それで、性能は低くなりますか?
ババクファギヒアン2015年

2
これらの「追加フィールド」がすでに定義されている場合、それは間違いなく「実際のフィールド」として行うのが最善です。そしてもちろん、大規模なクエリで無制限の数の結合を実行すると、負荷が大きくなります(ただし、それでも問題ない可能性があります)。メタデータが多いプロジェクトで私がやったことは、「メインアイテム」ごとに任意の数の「タグ」(EAVレコードとして)を許可することですが、「大きなクエリ」は事前定義されたタグ名のみを選択し、結合の総数を制限します(現在は典型的にはわずか4タグと約5の他の結合である)、およびユーザが特定の項目を選択すると、その後はすべて関連しfetchsが、単一の項目について。
ハビエル

しかしもちろん、その特定のシステムは現在hstoreフィールドに移植されています(PostgreSQLを使用する理由の1つにすぎません)
Javier

15
//この時点で、少し時間を取ってMagento / Adobe PSDフォーマットについてお話ししたいと思います。
// Magento / PSDは良いeコマースプラットフォーム/ フォーマットではありません。Magento / PSDは、悪いeコマースプラットフォーム/ フォーマットでもありません。それをそのように呼ぶことは
// ZencartやOsCommerceなど、他の悪いeコマースプラットフォーム/ 形式を侮辱します。いいえ、Magento / PSDはひどいeコマースプラットフォーム/ フォーマットです。持っている
//このコードで数週間作業しましたが、Magento / PSDに対する嫌悪感が激怒しました
//それは百万の太陽の激しい情熱で燃えます。

http://code.google.com/p/xee/source/browse/trunk/XeePhotoshopLoader.m?spec=svn28&r=11#107

内部モデルは、誰かがスキーマをボグルゲームに入れて封印し、ペイントシャッカーに入れるように、せいぜい風変わりです...

実世界:私はミドルウェアフルフィルメントアプリに取り組んでいます。ここに、住所情報を取得するためのクエリの1つを示します。

CREATE OR REPLACE VIEW sales_flat_addresses AS
SELECT sales_order_entity.parent_id AS order_id, 
       sales_order_entity.entity_id, 
       CONCAT(CONCAT(UCASE(MID(sales_order_entity_varchar.value,1,1)),MID(sales_order_entity_varchar.value,2)), "Address") as type, 
       GROUP_CONCAT( 
         CONCAT( eav_attribute.attribute_code," ::::: ", sales_order_entity_varchar.value )
         ORDER BY sales_order_entity_varchar.value DESC
         SEPARATOR '!!!!!' 
       ) as data
  FROM sales_order_entity
       INNER JOIN sales_order_entity_varchar ON sales_order_entity_varchar.entity_id = sales_order_entity.entity_id
       INNER JOIN eav_attribute ON eav_attribute.attribute_id = sales_order_entity_varchar.attribute_id
   AND sales_order_entity.entity_type_id =12
 GROUP BY sales_order_entity.entity_id
 ORDER BY eav_attribute.attribute_code = 'address_type'

注文の正確な住所情報を遅延して

-

概要: Magentoは次の場合にのみ使用してください。

  1. あなたは大きな袋を与えられています
  2. 絶対です
  3. 痛みを楽しむ

これは古い投稿ですが、クライアント向けにMagentoプロジェクトを開始した3か月前にこの記事が見つかれば良かったと思います。ボグル/ペイントシェーカーの類推で+1!
trevorc 2011年

1
かなり興味深いですが、magentoは、eコマースシステムの点では、道の王様のようです。多分それだけのマーケティングは非常に良いです
Herr

1
Magentoはメンテナンスレベルが高いため人気がありませんが、カスタマイズ機能により、アーキテクチャの変更やわずかな変更なしで誰でも新しい機能を実装できます。この機能には費用がかかります。
ディエゴメンデス

FEとBEの両方で3重の痛みとそれ以上の痛みを避けたい場合は、Magento 2に
近づかないでください

15

NoSQLデータベースについて誰も言及していないことに驚いています。

本番環境でNoSQLを実践したことはありませんが(MongoDBをテストして感銘を受けただけです)、NoSQLの目的は、さまざまな属性を持つアイテムを同じ「ドキュメント」に保存できることです。


MongoDBへの書き込みにはデータベースレベルのロックが必要であり、それが同時の本番トラフィックにとって意味することを考慮してください。
Bill Karwin 2013年

ロック期間がマイクロ秒のオーダーであることを考慮してください。
Hello World

12

ETLタイプのアプリケーションのように、パフォーマンスが主要な要件ではない場合、EAVには別の明確な利点があります。それは、差分保存です。

ドメインオブジェクトの最初の "バージョン"から現在の状態までの履歴を表示する機能が最も重要な要件である多くのアプリケーションを実装しました。そのドメインオブジェクトに多数の属性がある場合、つまり、変更ごとに対応するテーブルに新しい行を挿入する必要があります(履歴は失われるため、更新ではなく挿入です)。このドメインオブジェクトがPersonであり、Personsライフサイクル全体でさまざまな属性への平均100以上の変更を追跡する500k Personがあるとします。まれに、主要なドメインオブジェクトが1つしかないアプリケーションは珍しく、データベースのサイズが急速に制御不能になってしまうことにすぐに気付くでしょう。

簡単な解決策は、冗長な情報を繰り返し保存するのではなく、主要なドメインオブジェクトに対する差分の変更のみを保存することです。

すべてのモデルは、新しいビジネスニーズを反映するために時間とともに変化します。限目。EAVの使用は、私たちのボックスにある使用ツールの1つにすぎません。ただし、自動的に「不良」として分類されることはありません。


2
「EAVを使用することは、私たちの箱にあるツールの1つにすぎません。ただし、自動的に「不良」として分類されることはありません。」
Catchops

ところで、これはSCD(緩やかに変化する次元)と呼ばれます。また、バイテンポラル要件(タイプ4 SCDの特定のケース)では、このプロパティを持つ属性のEAVスキーマが必要です。NoSQLの99%にはネイティブ結合がないため、このタイプのデータとの「ライブ」結合が必要な場合は、EAVが唯一の方法です。
カウベルト2017

3

私は同じ問題で苦労しています。Magento(EAV)とJoomla(通常のリレーショナル構造)の2つの既存のeコマースソリューションに関する次のディスカッションをチェックするのは興味深いかもしれません:https : //forum.virtuemart.net/index.php?topic=58686.0

MagentoのEAVパフォーマンスは本当のショッパーです。

それが、正規化された構造に傾いている理由です。柔軟性の欠如を克服するために、編集できる別のデータディクショナリ(XMLまたは個別のDBテーブル)を将来追加することを考えています。それに基づいて、製品カテゴリを表示し、新しい属性セットと比較するためのアプリケーションコードは次のようになります。 SQLスクリプトとともに生成されます。

このようなアーキテクチャは、この場合のスイートスポットのようです-柔軟性とパフォーマンスを同時に発揮します。

問題は、ライブ環境でのALTER TABLEの頻繁な使用である可能性があります。私はPostgresを使用しているので、そのMVCCとトランザクションDDLで痛みを和らげることができれば幸いです。


2

私は、EAVの意味のある最低レベルの原子レベルでのモデリングにまだ投票しています。特定のユーザーコミュニティを対象とした標準、テクノロジー、アプリケーションで、コンテンツモデル、属性の繰り返しの必要性、粒度などを決定します。


2

それが製品カタログの属性にすぎず、したがってこれらの属性の検証要件がかなり制限されている場合、EAVの唯一の実際の欠点はクエリのパフォーマンスであり、クエリが属性を持つ複数の「もの」(製品)を処理する場合にのみ問題になります。 「id 234の製品のすべての属性を取得してください」というクエリのパフォーマンスは最適ではありませんが、それでも十分高速です。

1つの解決策は、SQLデータベース/ EAVモデルを製品カタログの管理/編集側でのみ使用し、製品を非正規化して検索可能にするプロセスを実行することです。すでに属性を持っているため、ファセット化が必要になる可能性が高いので、これはSolrまたはElasticSearchの可能性があります。このアプローチは、基本的にEAVモデルのすべての欠点を回避し、追加の複雑さは、更新時に完全な製品をJSONにシリアル化することに制限されます。


2

EAVには多くの欠点があります。

  1. 時間の経過に伴うパフォーマンスの低下アプリケーション内のデータの量が特定のサイズを超えて増加すると、そのデータの取得と操作の効率はますます低下します。
  2. SQLクエリは非常に複雑で、記述するのが困難です。
  3. データの整合性の問題。必要なすべてのフィールドに外部キーを定義することはできません。
  4. 独自のメタデータを定義して維持する必要があります。

1.これはほとんどのリレーショナルデータベースにも当てはまります。これが、シャーディングが発明された理由です。2.データモデリングは複雑で、実装が難しい場合があります。OLAPキューブスキーマの変更を待つのに数週間から数か月かかりました。3.すでにほとんどがソフトウェアで行われている4.リレーショナルスキーマをモデリングする場合は、これを「ERwin、Excel、およびVisioで」行う必要があります。
カウベルト2017

1

少し異なる問題があります。スパース値を持つ多くの属性(EAVを使用するのに十分な理由かもしれません)ではなく、スプレッドシートのようなものを保存したいのです。シートの列は変更できますが、シート内のすべてのセルにはデータが含まれます(スパースではありません)。

私は、EAVを使用するデザインと、Postgres ARRAYを使用してセルデータを格納するデザインの2つのベンチマークテスト行いました。

EAV ここに画像の説明を入力してください

アレイ ここに画像の説明を入力してください

どちらのスキーマにも適切な列にインデックスがあり、そのインデックスはプランナによって使用されます。

それは判明アレイベースのスキーマは桁速かったインサートとクエリの両方のために。簡単なテストから、どちらも線形にスケーリングされているように見えました。ただし、テストは完全ではありません。提案とフォークは歓迎します-彼らはMITライセンスの下にあります。


どのように配列モデルを使用してシートの列(つまりvlookup)を結合しましたか?独自の配列マージソート機能を書く必要はありませんか?セルのシートのid + x-coordinate + y-coordinateをセルの値のキーとして使用した場合、プリコンパイルされたマージソートと同じくらい良いものである可能性が非常に高いです。(Excelをエミュレートするには、0〜18278が列A〜ZZZであるx座標のルックアップテーブルを事前生成します(excelは16384で最大になります))。次に、sheet_id = uuidおよびx-coord = 0およびy座標の値を選択できます。 col 100の最初の1000行を取得するには、1001未満
カウバート、

@cowbertあなたは正しい。実際には、関心のある列をロードして、Pythonで結合を行うだけです。スラック!
z0r 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.