-2

PHP MySQL でフォーラムを開発しています。フォーラムをできる限り効率的にしたい。

この2つのテーブルを作りました

  1. tbl_threads
  2. tbl_comments

さて、問題は、各コメントの下に好き嫌いのボタンがあることです。user_name好きなボタンまたは嫌いなボタンをクリックしたを で保存する必要がありますcomment_id。コンマ区切りのuser_namesを格納する列user_likesと列を作成しましたuser_dislikestbl_commentsしかし、このフォーラムで、これは効率的な方法ではないことを読みました。Likes と Dislikes を格納する 3 つ目のテーブルを作成し、データベース設計を 1NF に準拠させるようにアドバイスされました。

しかし問題は、3 番目のテーブルを作成し、次のtbl_user_opinionように 2 つのフィールドを作成すると、1. comment_id 2. type (好きか嫌いか)

したがって、各コメントの好き嫌いのデータを取得するには、ページにコメントがあるのと同じ数の SQL クエリを実行する必要があります。非効率ではないでしょうか。ここで私の側にいくつかの混乱があると思います。誰かがこれを明確にすることができますか。

4

2 に答える 2

0

次のようなリレーショナルスキームがあります。

これを解決するには2つの方法があります。最初の「クリーン」なものは、「like」テーブルを作成し、適切な列で「count(*)」を実行することです。

2つ目は、各コメントにカウンターを格納して、アップとダウンの数を示します。特定のユーザーがコメントに投票したかどうかを確認する場合は、1つのエントリを確認するだけで、独自のクエリとして簡単に処理し、データベースの外部で2つをマージできます(この場合、comment_idとユーザーが特定のスレッドで行った投票の種類。)

カンマ区切りリストを使用したアプローチは、高度なインテリジェンスまたは大量の解析文字列なしでは解析できないため、パフォーマンスが高くありません。あなたがデータベースを持っているなら-それを使ってください!

(「1つの情報-1つのデータセット」!)

于 2013-03-03T11:24:21.533 に答える
0

コンマ区切りのリストは原子性の原則に違反しているため、1NF に違反しています。参照整合性を維持するのに苦労し、ほとんどの場合、クエリも同様です。

正規化された方法でそれを行う 1 つの方法を次に示します。

ここに画像の説明を入力

これは非常にクラスタリングに適しています。同じコメントに属する賛成票を物理的に近くにグループ化する (反対票も同じ) ため、次のクエリがかなり効率的になります。

SELECT
    COMMENT.COMMENT_ID,
    <other COMMENT fields>,
    COUNT(DISTINCT UP_VOTE.USER_ID) - COUNT(DISTINCT DOWN_VOTE.USER_ID) SCORE
FROM COMMENT
    LEFT JOIN UP_VOTE
        ON COMMENT.COMMENT_ID = UP_VOTE.COMMENT_ID
    LEFT JOIN DOWN_VOTE
        ON COMMENT.COMMENT_ID = DOWN_VOTE.COMMENT_ID
WHERE
    COMMENT.COMMENT_ID = <whatever>
GROUP BY
    COMMENT.COMMENT_ID,
    <other COMMENT fields>;

[SQLフィドル]

十分に高速に動作する場合は、現実的な量のデータで測定してください。そうでない場合は、モデルを非正規化し、合計スコアを COMMENT テーブルにキャッシュし、新しい行が *_VOTE テーブルに挿入または削除されるたびに、トリガーを介してスコアを最新に保ちます。

特定のユーザーが投票したコメントも取得する必要がある場合は、*_VOTE {USER_ID, COMMENT_ID}、つまり上記のプライマリ/クラスタリング キーの逆のインデックスが必要になります。1


1これが、1 (賛成票の場合) または -1 (反対票の場合) のいずれかになる追加フィールドを含むVOTEテーブルを1 つだけ使用しなかった理由の 1 つです。インデックス。

于 2013-03-04T11:51:21.040 に答える