フォーラムのスレッド投票/ビューのデータベース スキーマ、およびビュー数を増加および表示するための戦略
-
20-09-2019 - |
質問
今のところ重要な場合は、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 にはそのような機能が (まだ) 組み込まれていないため、 慣用的なユーザーレベルの実装