web-dev-qa-db-ja.com

多次元データの関係を解決する方法

プログラムで解決できるという問題がありますが、個人的な(テスト)プロジェクトでは、リレーショナルモデルで修正できるかどうかを確認しようとしています。

これらのプロパティを寸法として持つ複雑なファッション製品のパンツを想像してください。

  • 長さ(35,36,37,38)
  • サイズ(32,33,34,35)
  • 色(白、赤、青、黄、緑)
  • ニーパッチ(ウッドカッター、ブラウン、シルバー)
  • リンクベルト(ブラウン、ベージュ、ブラック)

だから4*4*5*3*3 = 720製品のバリエーション。私はこれが極端であることを知っていますが、私のシステムが後のフェーズでそれを処理できるかどうかを即座にテストするために純粋にこれを行っています。

だから私は持っています:

製品

id
name

プロパティ

id
name

RDBMSロジックを別にすると、次のようなテーブルが得られます。もちろん、常にプロパティを追加し、nullを大量に追加するため、これは不可能です。

製品バリエーション

 id
 product_id
 property_1_id
 property_2_id
 property_3_id
...etc.

したがって、これは、通常の製品で使用している通常の色/サイズの組み合わせよりも少し難しいです。

これで、この方法を偽造して、次のようにProductvariantsの1つのフィールドにプロパティIDのシリアル化をダンプできます。

製品バリエーション

id
product_id
properties {1, 2, 3}

..そして、それらを私のORMで分割しますが、これにより、将来必要なクエリが大幅に増加し(数万の製品バリエーションがあるため)、最適化はその方法では不可能と思われます。

誰かがこれについての経験を持っていますか? MySQLを使用しています。

2
User2910293

私は、似たような(私は信じている)何か、何千もの異なるフィールドタイプと常に新しいフィールドタイプが存在する可能性のある科学データベースを使用した経験があります。これは、あなたが試みているように見えるのと同様に、私たちがそれを解決する方法です。問題は、(誰かが示唆したように)行を適切な形式に再構築し、アプリケーションに表示することです。これは2回のスイープで行いました。最初に、データベースに保存されたデータ(フィールドの場所やタイプなど)から画面を動的に作成し、次に利用可能な値からデータを入力しました。

まず、各フィールドの値を格納する値テーブルを作成しました。このテーブルはすべての値を保持するため、次のようになります。

ValueID
ItemID
FieldID
Value (e.g. "32" for size 32, "White" for a colour field etc)

次に、各フィールドの説明を保持するフィールドテーブルを作成しました。

FieldID
FieldName (e.g. Colour,size)
ScreenID
FieldDisplayName (used for displaying the name on the screen)
FieldDisplayNameXLocation (these next 4 define the location on the screen of the label and editing field)
FieldDisplayNameYLocation
FieldXLocation 
FieldYLocation
FieldSize
FieldType (this is used for checking values are valid and for what type of field to display)

そして最後にScreenテーブル:

ScreenID
ScreenTitle
Screen Menus
etc...

次に、ユーザーの画面選択に応じて、画面とフィールドテーブルからデータをプルし、画面を動的に構築する「画面構築エンジン」を作成します。

SELECT ScreenTitle, ScreenMenus, ..., FieldID, FieldName, 
FieldDisplayName, FieldLocations, FieldSize, FieldType 
FROM Screen s INNER JOIN Field f ON s.ScreenID = f.ScreenID

これにより、エンジンが画面を構築するためのデータが得られます。画面は空白のキャンバスとして開始され、フィールドはありません。画面は、クエリによって返されるフィールドのタイプ/サイズと場所を使用して構築されます。次に、選択したアイテムに基づいて値テーブルからデータを抽出し、可視フィールドに挿入します。

SELECT ValueID, ItemID, FieldID, Value
FROM Field f INNER JOIN Value v ON f.FieldID = v.ValueID
WHERE ItemID = <user item ID entered>

これにより値が返され、エンジンは各値を画面の適切なフィールドに挿入します。

これは、実装するとうまくいき、テーブルに行を追加するだけで、アプリケーションとデータベース側に文字通り新しい「フィールド」を追加できるようになります。基本的に各フィールドはフィールドテーブルの行であり、行はフィールドが何であるかを定義します。ある時点で、約3秒でデータを挿入できるようにフィールドとラベルが定義された3つのまったく新しい画面を追加しました。ユーザーはアプリケーションを終了する必要さえありませんでした。画面が移動するとすぐに、画面は新しいデータベースフィールドと画面データで更新されます。

このアプローチの明らかな問題は次のとおりです。

  • 画面を構築するためのエンジンを作成する必要性に加えて、通常の方法では機能しないアプリケーションを維持するための関連オーバーヘッド(私たちは10 Mb LANを介したVB6/SQL Server 2000バックエンドであり、正常に機能していました)。
  • データベースをダブルヒットして画面を作成し、それに値を入力する
  • 有効なフィールド値をテストするためのビジネスロジックを作成する必要性(つまり、intがintであり、特別な分類フィールドが54.7D.98のように正しく入力されていることを確認してください)
  • 標準システムとの相互運用性
  • 複雑なSQLを必要とする標準的な方法でデータを表示することの難しさ
  • 多くのユーザーがシステムにアクセスしていた場合(多くの場合、同時ユーザー数は30以上)、システムの速度が大幅に低下しました(明らかにネットワーク速度/サーバー速度に依存します)。
  • 複雑な同時実行の問題により、デッドロックやその他の潜在的なデータ損失の問題が発生することがありました(ほとんどの場合、1人のユーザーが一度に1つのアイテムを編集できるようにすることで解決します)
  • 待ち時間の問題のため、WANを介した分散システムには適さない

ただし、次のような利点があります。

  • 多くのフィールドと画面をほとんど問題なくすばやく追加する機能
  • 管理オーバーヘッドを削減し、最終的にスーパーユーザーが必要なフィールドを定義および描画するために使用できるリバースビルドエンジンを構築しました。X/ Y位置の値とフィールドタイプはテストデータベースにアップロードされ、準備が整ったときにライブにプッシュされます。
  • 非常にシンプルで理解しやすい(頭に浮かんだら)データベースロジック
1
blobbles

製品

ProdId
ProdName

プロパティ

(PropId) (primary key, if required)
ProdId (composite key)
PropCode (composite key)
PropValue (composite key) (if storing a specific value, otherwise you can remove this to simply store the possible properties for any given product)

基本的に、すべてが単一の製品を指す特定のプロパティに複数の値を格納します。複合キーは一意である必要があり、PropCodeを別のテーブルにリンクするか、エントリの値を制限することにより、データの整合性を確保する必要があります。

1
Zack