フォーラムのスレッド投票/ビューのデータベース スキーマ、およびビュー数を増加および表示するための戦略

StackOverflow https://stackoverflow.com/questions/1944055

質問

今のところ重要な場合は、mysql/myisamを使用していますが、postgresqlを使用することができます。memcached の使用にも前向きです。

フォーラムのスレッドを保存するために使用されるテーブルを考えてみましょう。

id forum_name post_date
1  Hey!       2009-01-01 12:00:00
  • 投票、ビュー、カウンターなどのスレッド関連エンティティを保存するベスト プラクティスは何ですか?

したほうがいい..

次のような別のテーブルを作成します。

id thread_id views
1  1         532

それとも初期スレッドテーブルの列として保持しますか?

id forum_name post_date              views
1  Hey!       2009-01-01 12:00:00    532

もう 1 つの関連した情報ですが、ページビューを表示して増やすための実際的な解決策は何ですか?これを読みました そして、値を一定期間キャッシュできるようですが、増加する部分については正確にはわかりませんでした。おそらく、値をどこかのフラットファイルに保存し、cronjobsで定期的にデータベースフォーラムのビューを1時間ごとに更新するようなものです。 ?

編集:明確にするために、投票はスレッドごとに 1 票の SO と同様であり、逆転する可能性があります。カウンターについて私が何を言いたかったのかは気にしないでください。

役に立ちましたか?

解決

投票

スレッドテーブルに加えて 2 つのテーブルを定義することをお勧めします。 VOTE_CODES そして THREAD_VOTES. 。一見すると、正規化されすぎているように見えますが、この形式を使用すると、DML を大幅に変更することなく投票値を変更できます。

VOTE_CODES テーブル

  • vote_code, 、主キー、IE:上下
  • vote_cast_value -- 賛成/反対の投票に起因する値
  • vote_caster_value -- キャスターに影響を与える否定投票の SO スタイルを維持したい場合はオプション。

THREAD_VOTES テーブル

  • thread_id
  • user_id
  • vote_code

のすべての列 THREAD_VOTES は主キーです。これにより、特定のユーザーとスレッドに対して、投票コードと同じ数の行しか存在できないことが保証されます。コードが 2 つだけであると仮定すると、どちらかのコードを持つレコードが 2 つしか存在しないため、これにより投票を取り消す機能がサポートされます。

ビュー

以下のものを保管することをお勧めします。

  • スレッドID
  • IPアドレス
  • user_agent --大まかなブラウザ キャプチャ
  • タイムスタンプ

上記はすべて主キーです。テーブルへのデータの入力は高速ですが、ビュー内に計算列を作成して、より正確なレポートを作成できるようになります。

他のヒント

ロックを実装する必要があるため、フラット ファイルは明らかに悪い考えです (DB はすでにそれを実行しており、コードのバグは少ないです)。

リレーショナル データベースの設計は、科学というよりむしろ芸術です。あなたが持つことができます

CREATE TABLE threads (
  tid THREADID
, title THREADTITLE
, views COUNTER
, PRIMARY KEY (tid)
);

そしてそれはそれ以上でもそれ以下でも「正しい」わけではない

CREATE TABLE threads (
  tid THREADID
, title THREADTITLE
, PRIMARY KEY (tid)
);

CREATE TABLE views (
  tid THREADID
, views COUNTER
, PRIMARY KEY (tid)
, FOREIGN KEY (tid)
  REFERENCES threads
);

それは本当にあなた次第です。

私ならこう言います:最初は最も単純なものから始めて、必要に応じてより複雑にしてください (e.g.パフォーマンス上の理由から)。IOW:置く views COUNTER の属性 threads. 。トラフィックがパフォーマンスに悪影響を及ぼしていることが判明した場合 (更新が多すぎる場合) threads.views 属性は、DBMS が他の属性の不変データをシャッフルする必要があることを意味します)、いつでもテーブルを 2 つに分割し、それらを結合するビューに置き換えることができます。ほら、不変 (またはほとんど変更されない) データが揮発性データから分離されているため、インターフェイスは変わりません。

もちろん、PostgreSQL を使用してください。上記のコードはその dbms で有効です。以下を追加するだけです。

CREATE DOMAIN threadid
AS INT NOT NULL;

CREATE DOMAIN threadtitle
AS TEXT NOT NULL
CHECK (LENGTH(VALUE) > 0);

CREATE DOMAIN counter
AS INT NOT NULL
CHECK (VALUE > 0);

編集 OMG Ponies のコメントに反論するには:もちろん安全です。

UPDATE threads SET
  views = views + 1
WHERE tid = X

成功するか救済されるかのどちらかです。

編集2 投票の側面への考慮を追加する

仕様は次のとおりだとします。ユーザーはスレッドに賛成 (+1) または反対 (-1) 投票できますが、特定のスレッドに対する投票の合計が |1| を超えることはできず、履歴は無関係です。ユーザーはスレッドに賛成票を投じ、次に反対票を投じて「投票なし」にリセットし、次に再度反対票を投じて「反対票」などに投票することができます。

CREATE DOMAIN vote
AS INT NOT NULL
CHECK (VALUE BETWEEN -1 AND 1);

CREATE TABLE votes (
  tid THREADID
, uid USERID
, vote VOTE
, PRIMARY KEY (tid, uid)
);

MySQL では、次のことができます

INSERT INTO votes (
  tid
, uid
, vote
) VALUES (
  X
, Y
, Z -- +1 or -1
)
ON DUPLICATE KEY UPDATE
vote = vote + Z

残念ながら、PostgreSQL にはそのような機能が (まだ) 組み込まれていないため、 慣用的なユーザーレベルの実装

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top