5

ユーザーは自分の情報を更新できます。情報はテーブル内の定義された数の列に保存されます (user ( id INT, email VARCHAR, phone VARCHAR, address VARCHAR )例: )。

私は、Wordpress のような他の実装を見てきました。これは、ユーザーのこの情報をusermetalayoutと呼ばれるテーブルに格納します( umeta_id INT, user_id INT, meta_key VARCHAR, meta_value VARCHAR )

私が実装したい変更ログでは、そのようなソリューションを使用するか、(その方が良いと思います)、次のようなレイアウトを作成するかを評価していますuserLog ( id INT, date TIMESTAMP, email VARCHAR, phone VARCHAR, address VARCHAR )
したがって、特定の日付にユーザーが持っていたすべての情報の履歴を取得できます。行は変更のみを記録し、変更されていない列に NULL を持ちます。

最初の質問: この種のレイアウトには、適切な情報を挿入するだけで新しい情報タイプを作成できる以外に利点はありますmeta_keyか?
私の環境でパフォーマンスが問題になる場合、このレイアウトはあまり適切ではないかもしれないと思うことがありますVARCHAR

2 番目の質問: ストレージと選択/挿入の効率は、私が検討している 2 つのソリューション間で実際に違いを生むことができますか?
どのソリューションが、他のソリューションよりも少ない (または多い) スペース消費および/または少ない (または多い) 選択/挿入効率である必要がありますか?またその理由は?

4

3 に答える 3

2

必ずしも答えではないにしても、いくつかの考え:

明らかに、変更ログは必須であるため、ユーザーごとに 1 行の元の構造は解決策ではありません。したがって、次のいずれかの選択について話しています。

  1. 各ユーザーの情報セット全体のバージョンごとに 1 行。また
  2. 各ユーザーの情報のバージョンごとに 1 行

解決策 1 は、

userLog ( id INT, date TIMESTAMP, email VARCHAR, phone VARCHAR, address VARCHAR )

ソリューション 2 は、Wordpress のものに対応します。

umeta_id INT, user_id INT, meta_key VARCHAR, meta_value VARCHAR

あなたの質問 1: Solution2 の利点はわかりませんが、後でユーザーの (たとえば) Web サイトの URL や (たとえば) 好きな色もキャプチャすることにした場合は、meta_key を追加することでそれを行うことができます。 . しかし、Solution1 の下でこれを同様に簡単に行うことができます。

ALTER TABLE userlog ADD COLUMN WebSiteURL(etc)

それは難しいことではありません。あなたのショップの DBA が異常にドーベルマンのようでない限り ( ;) )。変更ログを保持しているため、(変更時に) 既存のすべてのユーザーの WebsiteURL 列は空白になります。しかし、それはまさにあなたが望んでいることです: システムが以前にそれをキャプチャしたことがなかったので、あなたは彼らの Web サイト URL を知りません。確かに、新しい列は NULLABLE である必要がありますが、ユーザー情報を取得するために使用している方法で必要な列として電子メール、電話、および住所が要求されない限り、「初期」データであってもそれは避けられない可能性があります。

私にとって、meta_key ソリューションの欠点は利点を上回ります。欠点は次のとおりです。

  • 1 人のユーザーのユーザー情報を 1 つの
    行にピボットするには、ピボット コードを開発する必要があります。1 つの行でユーザー情報を取得するすべての場所で、このコードを呼び出す必要があります。対照的に、Solution1 は

    SELECT userID,[all user info] FROM userLog INNER JOIN (SELECT userID,MAX(datechanged) AS LatestDAteChanged FROM userlog GROUP BY userID) a ON userlog.userid=a.userID AND userlog.DateChanged=a.LatestDAteChanged

    これはピボットよりもはるかに効率的です。UserID,DateChanged のインデックスを使用すると、これは風のように実行されます。

  • userinfo テーブル (Email、Email、Email、Email、Email) で複数回 meta_key 値を本当に保持したい場合を除き、追加の Meta_Key_Lookup テーブルが必要になります。

2 番目の質問: 究極のスペース効率については、はい、meta_key Solution2 が最適です。特に VARCHAR メタキーを使用せず、メタキー ID 値を使用し、別の meta_key ルックアップ テーブル (例: 1=Email、2=Phone など) がある場合。しかし、ストレージの価格が事実上ゼロであることと、このソリューションに伴う問題点を考えると、これが meta_key ソリューション 2 の決定的な議論になるとは思いません。

(メモ/考え: 私見ですが、値が変更されていないソリューション1で NULL 値を保持するというあなたの考えは間違った道です。最新の電子メール、次に電話、次にアドレス (個別に) を取得しようとするコーディング他のソリューションで必要とされるピボットとほぼ同じくらいコーディング/テストが難しく、サーバーを実行するのも困難です. そして、ストレージの削減は限界です. 何かが変わるたびに行全体を保持するだけです.例を挙げているだけで、実際のユーザー情報セットは 50 列幅です...)

私見ストレージの問題は決定的ではありません。それでは、SELECT/INSERT の効率に目を向けましょう。

この問題に関しては、Solution1 が依然として勝つと思います。挿入では、SOLution1 が勝ちます。ユーザーが情報内のすべてのフィールドを変更しても、1 行だけが挿入されます。SELECTS では、ソリューション 1 が再び勝利します。ユーザーごとに最新の情報 (上記のコード) を表示するだけで済みます。これは、SQL が最適化されている種類のものです。対照的に、Solution2 にはピボットが必要です。これは、SQL が苦手とするものです。

于 2012-11-19T18:25:15.980 に答える
0

標準 SQL ソリューションについては @sebt に同意します。

PostgreSQL で柔軟なソリューションが必要な場合は、hstore タイプをお勧めします ( postgresql 9.1 docs )。このタイプは、多くのキー => 値のペアを 1 つの列に格納できます。
この列を挿入、検索、および索引付けする方法は多数あります。ドキュメンテーションは、探し始める良い方法です。

于 2012-11-19T19:22:55.670 に答える
0

最良の選択は、何をしたいのか、つまり実行するクエリに大きく依存します (多くの場合と同様)。

WordPress のものはよくわかりません (個々のフィールドを行として保存するという事実はわかりますが、それがどこに収まるかはわかりません)。そのため、すべてのオプションをリストします。

  1. ユーザー テーブルと履歴テーブルに行ごとに個別のフィールドを格納する
  2. 行ごとに個々のフィールドを格納するのは履歴テーブルのみです
  3. 行ごとに個々のフィールドを保存するのはユーザー テーブルだけです
  4. 行ごとに個々のフィールドを保存しない
  5. ユーザーと履歴の両方に 1 つの結合テーブルを用意する
  6. 行ごとに個々のフィールドを格納するための 1 つの結合テーブルを用意する

(5) と (6) は、ほとんどの場合、オプションのようには見えません。履歴を取得するよりも、ユーザー (または多数のユーザー) の詳細を取得する方が多いと思われるからです (ほとんどのクエリが両方を同時に取得する場合を除きます)。

(1) と (3) は、詳細の多くが入力されていない場合を除き、推奨されません (したがって、他の場合には非常にまばらなテーブルになってしまいます)。

(4) は、ユーザーがすべての詳細を一度に変更する傾向がある場合に使用します。これはおそらく頻繁には発生しません。一度に 1 つまたは 2 つのフィールドを変更するだけだと思います。そのため、(2) は、特にユーザー テーブルに多くのフィールドがある (一度に 1 つまたは 2 つのフィールドを変更するだけの場合) 場合は、おそらくより適切なオプションです。

一般に、行ごとに個々のフィールドを保存することは、パフォーマンスを向上させるためのストレージ スペースを削減するためのものです (いくつかの空のフィールドがあると仮定すると、それ以外の場合、行ごとに個々のフィールドを保存することは明らかに悪いことです)。 . ここで主に選択について話していることに注意してください。これは、奇妙なことが起こっているか、一度に大量の挿入がない限り、一般的に遅い操作です。履歴については、一般にパフォーマンスよりもストレージの削減が優先されるため、(2) になります。

いずれにせよ、フィールドの追加は一般的に少し手間がかかるため、'UPDATE user ADD COLUMN col' と言うだけでは大したことではなく、自動化することもできます。これは、(4) よりも (2) を好むもう 1 つの (小さな) 理由です。

于 2012-11-23T14:03:29.643 に答える