-2

我正在开发一个 PHP MySQL 论坛。我想让我的论坛尽可能高效。

我做了这两张桌子

  1. tbl_threads
  2. tbl_comments

现在,问题是每个评论下都有一个喜欢和不喜欢的按钮。我必须存储user_name单击了喜欢或不喜欢按钮的comment_id. 我已经创建了一个 user_likes 列和一个user_dislikes用于tbl_comments存储逗号分隔的 user_names 的列。但是在这个论坛上,我读到这不是一种有效的方法。有人建议我创建第三个表来存储喜欢和不喜欢,并使我的数据库设计符合 1NF。

但问题是,如果我制作第三张表tbl_user_opinion并制作两个像这样的字段 1.comment_id 2.类型(喜欢或不喜欢)

那么,我是否必须运行与我的页面上的评论一样多的 sql 查询才能获取每个评论的喜欢和不喜欢数据。会不会低效。我认为我在这里有些困惑。有人可以澄清这一点。

4

2 回答 2

0

逗号分隔的列表违反了原子性原则,因此违反了 1NF。您将很难维护引用完整性,并且在大多数情况下,查询也是如此。

这是以标准化方式执行此操作的一种方法:

在此处输入图像描述

这对集群非常友好:它将属于同一评论的赞成票在物理上靠近在一起(反对票同上),使以下查询相当有效:

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 表中删除新行时通过触发器使其保持最新。

如果您还需要获取特定用户投票的评论,则需要 *_VOTE {USER_ID, COMMENT_ID} 上的索引,即上面的主键/集群键的反面。1


1这就是为什么我不只使用一个包含额外字段的 VOTE 表的原因之一,该字段可以是 1(表示赞成)或 -1(表示反对):用次要覆盖的效率较低索引。

于 2013-03-04T11:51:21.040 回答
0

你有一个这样的关系方案:

有两种方法可以解决这个问题。第一个,“干净”的一个是建立你的“喜欢”表,并在适当的列上做“计数(*)”。

第二个是在每条评论中存储一个计数器,指示那里有多少涨跌。如果您想检查,如果特定用户对评论投票,您只需要检查一个条目,您可以轻松地将它们作为自己的查询处理并将它们合并到您的数据库之外(为此使用查询导致 comment_id 和用户在特定线程中所做的投票。)

您使用逗号分隔列表的方法不是很高效,因为如果没有更高的智能或大量的解析字符串,您将无法解析它。如果你有一个数据库 - 使用它!

(“一个信息 - 一个数据集”!)

于 2013-03-03T11:24:21.533 回答