58

ユーザー設定の保存に使用するテーブルを設計する際のベスト プラクティスと見なされるオプションは、次のうちどれですか?

(オプション1)

USER_SETTINGS
-Id
-Code (example "Email_LimitMax")
-Value (example "5")
-UserId

(オプション 2)

たとえば、通知設定で作成が必要な設定ごとに新しいテーブルを作成します。

"USER_ALERT_SETTINGS"
-Id
-UserId
-EmailAdded (i.e true)
-EmailRemoved 
-PasswordChanged
...
...

"USER_EMAIL_SETTINGS"
-Id
-UserId
-EmailLimitMax
....

(オプション 3)

"USER"
-Name
...
-ConfigXML
4

5 に答える 5

113

他の回答は、さまざまなオプションの長所と短所をうまく概説しています。

オプション 1 (プロパティ バッグ) は、特にプロパティ バッグの弱点に対する保護を組み込む場合、ほとんどのアプリケーションにとって最適な全体的な設計であると考えています。

次の ERD を参照してください。

プロパティ バッグ ERD

上記の ERD では、USER_SETTINGテーブルは OP のものと非常によく似ています。違いは、varchar と列の代わりにCode、この設計には、許容される設定 (コード) と値の相互に排他的な 2 つの列を定義Valueするテーブルへの FK があることです。SETTING1 つのオプションは、あらゆる種類のユーザー入力を受け取ることができる varchar フィールドであり、もう 1 つは有効な値のテーブルへの FK です。

このSETTINGテーブルには、ユーザー設定を FK で定義するか、制約のない varchar 入力で定義するかを示すフラグもあります。に を追加しdata_typeて、SETTINGをエンコードおよび解釈する方法をシステムに指示することもできUSER_SETTING.unconstrained_valueます。必要に応じて、テーブルを追加してSETTING_GROUP、ユーザー メンテナンス用のさまざまな設定を整理することもできます。

この設計により、設定内容に関するルールをテーブル駆動することができます。これは便利で、柔軟性があり、保守が容易であり、自由参加を回避できます。


編集:いくつかの例を含むいくつかの詳細...

上記の ERD は、より多くの列の詳細 (SETTING の範囲値と ALLOWED_SETTING_VALUE の列) で拡張されていることに注意してください。

例としていくつかのサンプル レコードを示します。

SETTING:
+----+------------------+-------------+--------------+-----------+-----------+
| id | description      | constrained | data_type    | min_value | max_value |
+----+------------------+-------------+--------------+-----------+-----------+
| 10 | Favourite Colour | true        | alphanumeric | {null}    | {null}    |
| 11 | Item Max Limit   | false       | integer      | 0         | 9001      |
| 12 | Item Min Limit   | false       | integer      | 0         | 9000      |
+----+------------------+-------------+--------------+-----------+-----------+

ALLOWED_SETTING_VALUE:
+-----+------------+--------------+-----------+
| id  | setting_id | item_value   | caption   |
+-----+------------+--------------+-----------+
| 123 | 10         | #0000FF      | Blue      |
| 124 | 10         | #FFFF00      | Yellow    |
| 125 | 10         | #FF00FF      | Pink      |
+-----+------------+--------------+-----------+

USER_SETTING:
+------+---------+------------+--------------------------+---------------------+
| id   | user_id | setting_id | allowed_setting_value_id | unconstrained_value |
+------+---------+------------+--------------------------+---------------------+
| 5678 | 234     | 10         | 124                      | {null}              |
| 7890 | 234     | 11         | {null}                   | 100                 |
| 8901 | 234     | 12         | {null}                   | 1                   |
+------+---------+------------+--------------------------+---------------------+

これらの表から、決定できるユーザー設定の一部は、お気に入りの色、アイテムの最大制限、およびアイテムの最小制限であることがわかります。お気に入りの色は、英数字の選択リストです。アイテムの最小制限と最大制限は、許容範囲値が設定された数値です。このSETTING.constrained列は、ユーザーが関連する から選択するALLOWED_SETTING_VALUEか、または を入力する必要があるかを決定しUSER_SETTING.unconstrained_valueます。ユーザーが設定を操作できるようにする GUI は、提供するオプションと、 と と の両方の制限 (存在する場合) を適用する方法を理解する必要がありSETTING.data_typeます。min_valuemax_value

この設計を使用すると、ユーザーが選択 (または入力) した値にいくつかの基本的な制約/サニティ チェックを適用するのに十分なメタデータを含む、許容される設定をテーブルで駆動できます。

編集: クエリの例

上記のデータを使用して特定のユーザー ID の設定値をリストするサンプル SQL を次に示します。

-- DDL and sample data population...
CREATE TABLE SETTING
    (`id` int, `description` varchar(16)
     , `constrained` varchar(5), `data_type` varchar(12)
     , `min_value` varchar(6) NULL , `max_value` varchar(6) NULL)
;

INSERT INTO SETTING
    (`id`, `description`, `constrained`, `data_type`, `min_value`, `max_value`)
VALUES
    (10, 'Favourite Colour', 'true', 'alphanumeric', NULL, NULL),
    (11, 'Item Max Limit', 'false', 'integer', '0', '9001'),
    (12, 'Item Min Limit', 'false', 'integer', '0', '9000')
;

CREATE TABLE ALLOWED_SETTING_VALUE
    (`id` int, `setting_id` int, `item_value` varchar(7)
     , `caption` varchar(6))
;

INSERT INTO ALLOWED_SETTING_VALUE
    (`id`, `setting_id`, `item_value`, `caption`)
VALUES
    (123, 10, '#0000FF', 'Blue'),
    (124, 10, '#FFFF00', 'Yellow'),
    (125, 10, '#FF00FF', 'Pink')
;

CREATE TABLE USER_SETTING
    (`id` int, `user_id` int, `setting_id` int
     , `allowed_setting_value_id` varchar(6) NULL
     , `unconstrained_value` varchar(6) NULL)
;

INSERT INTO USER_SETTING
    (`id`, `user_id`, `setting_id`, `allowed_setting_value_id`, `unconstrained_value`)
VALUES
    (5678, 234, 10, '124', NULL),
    (7890, 234, 11, NULL, '100'),
    (8901, 234, 12, NULL, '1')
;

次に、ユーザーの設定を抽出する DML:

-- Show settings for a given user
select
  US.user_id 
, S1.description 
, S1.data_type 
, case when S1.constrained = 'true'
  then AV.item_value
  else US.unconstrained_value
  end value
, AV.caption
from USER_SETTING US
  inner join SETTING S1
    on US.setting_id = S1.id 
  left outer join ALLOWED_SETTING_VALUE AV
    on US.allowed_setting_value_id = AV.id
where US.user_id = 234

SQL Fiddleでこれを参照してください。

于 2012-04-19T12:34:37.580 に答える
15

オプション 1 (前述の「プロパティ バッグ」) は実装が簡単で、事前の分析はほとんど必要ありません。しかし、それには多くの欠点があります。

  1. UserSettings.Code の有効な値を制限したい場合は、有効なタグのリストの補助テーブルが必要です。そのため、(a) UserSettings.Code の検証がない – アプリケーション コードが任意の値をダンプする可能性があり、バグをキャッチする機会を逃すか、有効なタグの新しいリストにメンテナンスを追加する必要があります。

  2. UserSettings.Value には、おそらく、それに入る可能性のあるさまざまな値すべてに対応する文字列データ型があります。したがって、整数、ブール、浮動小数点数などの真のデータ型と、不正な値の挿入時に RDMBS によって行われるデータ型チェックが失われます。繰り返しになりますが、潜在的な QA 問題を自分で購入したことになります。文字列値の場合でも、列の長さを制限する機能が失われています。

  3. コードに基づいて列に DEFAULT 値を定義することはできません。したがって、EmailLimitMax をデフォルトの 5 にしたい場合は、それを行うことはできません。

  4. 同様に、無効な値を防ぐために値列に CHECK 制約を設定することはできません。

  5. プロパティ バッグのアプローチでは、SQL コードの検証が失われます。名前付き列アプローチでは、「UserID = x の UserSettings から Blah を選択する」というクエリは、Blah が存在しない場合に SQL エラーを受け取ります。SELECT がストアド プロシージャまたはビューにある場合、コードが本番環境に移行する前に、プロシージャ/ビューを適用するとエラーが発生します。プロパティ バッグ アプローチでは、NULL を取得するだけです。したがって、データベースによって提供される別の自動 QA 機能が失われ、検出されないバグが発生する可能性があります。

  6. 前述のように、条件が複数のタグに適用される UserID を検索するクエリは、記述するのが難しくなります。テストする条件ごとに、テーブルへの 1 つの結合が必要です。

  7. 残念ながら、プロパティ バッグは、アプリケーション開発者がアプリケーションの残りの部分でどのように使用されるかを分析せずに、新しいコードをプロパティ バッグに貼り付けることを勧めるものです。大規模なアプリケーションの場合、これは正式にモデル化されていないため、「隠れた」プロパティのソースになります。名前付き属性の代わりに純粋なタグ値を使用してオブジェクト モデルを実行するようなものです。これはエスケープ バルブを提供しますが、厳密に型指定された名前付き属性に対してコンパイラが提供するすべてのヘルプを見逃しています。または、スキーマ検証なしで本番 XML を実行するようなものです。

  8. 列名のアプローチは自己文書化されています。テーブル内の列のリストは、可能なユーザー設定が何であるかを開発者に伝えます。

プロパティ バッグを使用しました。しかし、それは逃げ弁としてだけであり、私はしばしばそれを後悔してきました. 私は、「ああ、その明示的な列をプロパティ バッグにすればよかった」とは決して言いませんでした。</p>

于 2012-04-18T16:12:33.073 に答える
13

この簡単な例を考えてみましょう。

UserTable (ユーザーの詳細を含む) と SettingsTable (設定の詳細を含む)の 2 つのテーブルがある場合。次に、以下に示すように、UserTable と SettingsTable を関連付けるための新しいテーブルUserSettingsを作成します。

ユーザー設定データベースの設計

この例から正しい解決策が見つかることを願っています。

于 2013-08-27T05:16:59.910 に答える
5

各オプションにはそれぞれの場所があり、選択は特定の状況によって異なります。以下の各オプションの長所と短所を比較しています。

オプション 1: 長所:

  • 多くのオプションを処理できます
  • 新しいオプションを簡単に追加できます
  • オプションを管理するための汎用インターフェースを開発できます。

オプション 1: 短所

  • 新しいオプションが追加されると、すべてのユーザー アカウントを新しいオプションで更新するのがより複雑になります。
  • オプション名は制御不能になる可能性があります
  • 許可されたオプション値の検証はより複雑であり、そのためには追加のメタデータが必要です

オプション 2: 長所

  • 各オプションは個別の列であるため、各オプションの検証はオプション 1 よりも簡単です。

オプション 2: 短所

  • 新しいオプションごとにデータベースの更新が必要です
  • 多くのオプションを使用すると、データベース テーブルが使いにくくなる可能性があります
于 2012-04-18T08:39:17.870 に答える
4

実行したいクエリの種類に依存するため、「最良」を評価するのは困難です。

オプション 1 (一般に「プロパティ バッグ」、「名前と値のペア」、または「エンティティ属性値」または EAV として知られています) を使用すると、スキーマが事前にわからないデータを簡単に格納できます。ただし、一般的なリレーショナル クエリを実行することは困難 (場合によっては不可能) になります。たとえば、同等の実行を想像してください

select count(*) 
from USER_ALERT_SETTINGS 
where EmailAdded = 1 
and Email_LimitMax > 5

これは、特にデータベース エンジンが数値的に意味のある方法で varchar フィールドを比較しない場合があるため、急速に非常に複雑になります (したがって、> 5" は期待どおりに機能しない可能性があります)。

実行したいクエリを作成し、それらのクエリを最もよくサポートする設計を確認します。個々のユーザーの制限を確認するだけであれば、プロパティ バッグで問題ありません。すべてのユーザーをレポートする必要がある場合は、おそらくそうではありません。

JSON や XML の場合も同様です。個々のレコードを保存する場合は問題ありませんが、すべてのユーザーのクエリやレポートが難しくなります。たとえば、電子メール アドレス「bob@domain.com」の構成設定を検索するとします。これには、ノード「電子メール アドレス」を見つけるためにすべての XML ドキュメントを検索する必要があります。

于 2012-04-18T13:18:00.733 に答える