74

商用アプリケーションを開発します。お客様はカスタムフィールドのサポートを求めています。たとえば、顧客フォームにフィールドを追加したいとします。

フィールド値とフィールドに関するメタデータを格納するための既知のデザインパターンは何ですか?

今のところ、次のオプションが表示されます。

オプション1:varchar型のField1、Field2、Field3、Field4列をCustomerテーブルに追加します。

オプション2:顧客テーブルにXMLタイプの単一の列を追加し、カスタムフィールドの値をxmlに格納します。

オプション3:varchar型の列を持つCustomerCustomFieldValueテーブルを追加し、その列に値を格納します。そのテーブルには、CustomerID、CustomFieldIDも含まれます。

CustomerID,  CustomFieldID, Value
10001,       1001,          '02/12/2009 8:00 AM'
10001,       1002,          '18.26'
10002,       1001,          '01/12/2009 8:00 AM'
10002,       1002,          '50.26'

CustomFieldIDは、CustomFieldID、FieldName、FieldValueTypeIDの列を持つCustomFieldという別のテーブルのIDになります。

オプション4:可能な各値タイプの列を持つCustomerCustomFieldValueテーブルを追加し、右側の列に値を格納します。#3と似ていますが、フィールド値は強い型の列を使用して格納されます。

CustomerID,  CustomFieldID, DateValue,           StringValue,       NumericValue                 
10001,       1001,          02/12/2009 8:00 AM,  null,              null
10001,       1002,          null,                null,              18.26
10002,       1001,          01/12/2009 8:00 AM,  null,              null
10002,       1002,          null,                null,              50.26

オプション5:オプション3および4は、単一の概念(顧客)に固有のテーブルを使用します。私たちのクライアントは、他の形式のカスタムフィールドも求めています。代わりに、システム全体のカスタムフィールドストレージシステムを用意する必要がありますか?したがって、CustomerCustomFieldValue、EmployeeCustomFieldValue、InvoiceCustomFieldValueなどの複数のテーブルを使用する代わりに、CustomFieldValueという名前の単一のテーブルを使用しますか?私にはもっとエレガントに見えますが、それがパフォーマンスのボトルネックになるのではないでしょうか。

これらのアプローチのいずれかを使用しましたか?成功しましたか?どのアプローチを選択しますか?私が考慮すべき他のアプローチを知っていますか?

また、私のクライアントは、カスタムフィールドが他のテーブルのデータを参照できるようにしたいと考えています。たとえば、クライアントは「お気に入りの支払い方法」フィールドを顧客に追加したい場合があります。支払い方法は、システムの他の場所で定義されています。それは写真の「外部キー」の主題をもたらします。カスタムフィールドテーブルに格納されている値が有効な値であることを確認するために、制約を作成する必要がありますか?

ありがとう

======================

2009年7月27日編集:

ご回答ありがとうございます。アプローチのリストは今ではかなり包括的であるように思われます。オプション2(単一のXML列)を選択しました。今のところ、実装するのが最も簡単でした。要件がより複雑になり、サポートするカスタムフィールドの数が増えるため、より厳密に定義されたアプローチに抵抗する必要があります。

4

7 に答える 7

15

オプション3、4、または5が適切である可能性が最も高いという以下のポスターに同意します。ただし、提案された実装にはそれぞれ利点とコストがあります。特定の要件に合わせて選択することをお勧めします。例えば:

  1. オプション1の長所:実装が高速です。カスタムフィールドでのDBアクション(検索、並べ替え)を許可します。
    オプション1短所:カスタムフィールドは汎用であるため、厳密に型指定されたフィールドはありません。データベーステーブルは非効率的で、サイズ的には、使用されることのない多くの無関係なフィールドがあります。許可されるカスタムフィールドの数を予測する必要があります。
  2. オプション2の長所:実装が高速です。柔軟性があり、任意の数とタイプのカスタムフィールドを使用できます。
    オプション2の短所:カスタムフィールドでDBアクションを実行することはできません。これは、後でカスタムフィールドを表示するか、顧客ごとにのみデータをわずかに操作するだけの場合に最適です。
  3. オプション3の長所:柔軟性と効率性の両方。DBアクションは実行できますが、データは、無駄なスペースを減らすためにいくらか正規化されています。タイプまたはソース情報を指定するために使用できる列を追加するというunknown(google)の提案に同意します。オプション3の短所:開発時間とクエリの複雑さがわずかに増加しますが、ここでは実際にはそれほど多くの短所はありません。
  4. オプション4はオプション3と同じですが、入力したデータをDBレベルで操作できる点が異なります。オプション3のリンクテーブルにタイプ情報を追加すると、アプリケーションレベルでより多くの操作を実行できますが、たとえば、DBは比較や並べ替えを実行できなくなります。3と4の間の選択は、この要件によって異なります。
  5. オプション5は3または4と同じですが、ソリューションを多くの異なるテーブルに適用するためのさらに柔軟性があります。この場合のコストは、このテーブルのサイズがはるかに大きくなることです。カスタムフィールドに到達するために多くの高価な結合操作を実行している場合、このソリューションは適切に拡張できない可能性があります。

PS以下で説明するように、「デザインパターン」という用語は通常、オブジェクト指向プログラミングを指します。データベース設計の問題の解決策を探しています。つまり、設計パターンに関するほとんどのアドバイスは適用できません。

于 2009-07-14T18:18:13.483 に答える
11

アプリケーションコードに関する限り、私にはわかりません。カスタムフィールドは、データベース内のEAVモデルから大きな恩恵を受けることを私は知っています。

以下のコメントによると、このモデルで犯す可能性のある最も重大な間違いは、外部キーをモデルに入れることです。FriendIDやTypeIDのようなものをこのモデルに入れないでください。このモデルを一般的なリレーショナルモデルと組み合わせて使用​​し、外部キーフィールドをテーブル列に適切に保持します。

2つ目の重大な間違いは、すべての要素で報告する必要のあるデータをこのモデルに配置することです。たとえば、このモデルにUsernameのようなものを入れると、ユーザーにアクセスしたいときに、せいぜい参加することを約束したユーザー名を知る必要がある場合、または2nクエリ(nは表示しているユーザーの数)を意味します。 。通常、すべてのUser要素にUsernameプロパティが必要になると考えると、これもテーブルの列に残しておく必要があることが明らかになります。

ただし、このモデルをカスタムユーザーフィールドで使用している場合は問題ありません。ユーザーがリレーショナルデータを入力し、EAVモデルが検索にそれほど悪影響を及ぼさないという多くの状況を想像することはできません。

最後に、これからデータを結合して、きれいなレコードセットを取得しようとしないでください。元のレコードを取得してから、エンティティのレコードのセットを取得します。テーブルに参加したくなった場合は、上記のように2番目の間違いを犯した可能性があります。

于 2009-07-14T17:23:38.913 に答える
5

オブジェクト指向言語で開発している場合は、ここで適応オブジェクトモデルについて話します。オブジェクト指向言語でそれらを実装する方法について書かれた記事はかなりありますが、データストア側を設計する方法についてはそれほど多くの情報はありません。

私が働いている会社では、リレーショナルデータベースを使用してAOMデータを格納することで問題を解決しました。人、ネットワークデバイス、企業など、ドメイン内のさまざまな「エンティティ」をすべて表示するための中央エンティティテーブルがあります。実際の「フォームフィールド」は、入力されたデータテーブルに格納されるため、次のテーブルが1つあります。文字列、日付などに1つ。すべてのデータテーブルには、エンティティテーブルを指す外部キーがあります。また、タイプ側、つまり特定のエンティティが持つことができる属性(フォームフィールド)の種類を示すテーブルも必要です。この情報は、データテーブルのデータを解釈するために使用されます。

私たちのソリューションの長所は、エンティティ間の参照、複数値など、コードを変更せずにすべてをモデル化できることです。フィールドにビジネスルールと検証を追加することも可能であり、それらはすべての形式で再利用できます。短所は、プログラミングモデルを理解するのが非常に簡単ではなく、クエリのパフォーマンスがより一般的なDB設計よりも悪くなることです。リレーショナルデータベース以外のソリューションは、AOMにとってより優れていて簡単だったかもしれません。

実用的なデータストアを使用して優れたAOMを構築するのは大変な作業であり、高度なスキルを持つ開発者がいない場合はお勧めしません。たぶんいつか、この種の要件に対応するOSソリューションが登場するでしょう。

カスタムフィールドについては、SOで以前に説明しました。

于 2009-07-14T17:40:50.203 に答える
3

オプション3のようなものが進むべき道であり、私は以前にこの方法を使用しました。単一のテーブルを作成して、追加のプロパティとそれに対応する値を定義します。これは、CustomerテーブルとCustomerCustomFieldテーブルの間の1-N関係になります(それぞれ)。カスタムプロパティとの関係の定義に関する2番目の質問は、考えるべきことです。最初に頭に浮かぶのは、プロパティ値がバインドされているテーブルを含むDataSourceフィールドを追加することです。したがって、基本的にCustomerCustomFieldは次のようになります。

  1. 顧客ID
  2. 財産
  3. 価値
  4. ValueDataSource(null許容)

これにより、特定のデータ構造にバインドするか、バインドされていない値を指定できるようになります。このモデルをさらに正規化することもできますが、このようなものは機能する可能性があり、コードで処理するのに十分簡単なはずです。

于 2009-07-14T17:41:04.027 に答える
3

オプション4または5が私の選択です。データが重要な場合は、オプション3で型情報を破棄することはしません(完全な型チェックを自分で実装しようとするかもしれませんが、それはかなり大きな仕事であり、データベースエンジンはすでにそれを行っています)。

いくつかの考え:

  • CustomFieldsがあることを確認してください。DataType
    • でUDFベースのチェック制約を使用CustomFieldValuesして、で指定された列CustomFields.DataTypeがnull以外であることを確認します。
    • また、null以外の値が1つだけあることを確認するために、標準のチェック制約が必要になります。
  • 外部キーに関しては、これらを個別にモデル化しDataTypeます。
    • 潜在的なクロステーブル参照ごとに、独自の列が必要になります。これは、参照整合性を維持するため、優れています。
    • とにかくアプリケーションコードでこれらの関係をサポートする必要があるため、データベースにハードコーディングされているという事実が実際に機能を制限することはありません。
    • ORMを使用している場合は、これもORMとうまく調和します。
  • オプション5の場合、中間テーブルを使用して関係をモデル化します。
    • はまだありますがCustomerCustomFieldValue、代わりにと列のみがCustomerIDありCustomFieldValueIDます。
  • あらゆる段階で、制約についてじっくり考えてください。これはトリッキーなことであり、1つのミスステップがラインに完全な大混乱を引き起こす可能性があります。

現在開発中のアプリケーションで使用しています。まだ問題はありませんが、EAVのデザインはまだ私を怖がらせています。ただ注意してください。

余談ですが、XMLも良い選択かもしれません。直接の経験からはあまりわかりませんが、データ設計を始めるときに考えた選択肢のひとつで、かなり有望に見えました。

于 2009-07-14T18:00:33.863 に答える
0

これらの「余分な」フィールドが偶発的であり、それらを検索する必要がない場合は、通常、オプション2を選択します(ただし、XMLよりもJSONの方が優れています)。カスタムフィールドで検索を行う場合、オプション3を実行するのは難しくありません。通常、SQLオプティマイザーはそれから妥当なパフォーマンスを得ることができます。

于 2009-07-14T17:59:20.650 に答える
0

私は現在、これと同じ問題のあるプロジェクトに取り組んでおり、オプション3を使用することを選択しましたが、FieldType = "list"の場合に備えて、FieldTypeフィールドとListSourceフィールドを追加しました。ListSourceフィールドは、クエリ、SQLビュー、関数名、またはリストのオプションのリストを生成するものにすることができます。私の状況でこのようなフィールドを保存しようとする際の最大の問題は、このフィールドリストが変更される可能性があり、ユーザーが後でデータを編集できるようになることです。したがって、フィールドリストが変更され、編集に移動した場合の対処方法。そのシナリオに対する私の解決策は、リストが変更されていない場合にのみ編集を許可し、変更されている場合は読み取り専用データを表示することでした。

于 2017-05-26T19:48:30.857 に答える