我正在开发PHP MySQL论坛。我想让我的论坛尽可能高效。
我已经制作了这两个表
现在,问题是每个评论下都有一个喜欢和不喜欢的按钮。我必须存储已使用user_name
点击了喜欢或不喜欢按钮的comment_id
。我在user_dislikes
中创建了一列user_likes和一列tbl_comments
来存储逗号分隔的user_names。但在这个论坛上,我已经读到这不是一种有效的方法。我被建议创建第三个表来存储喜欢和不喜欢,并使我的数据库设计符合1NF。
但问题是,如果我制作第三个表tbl_user_opinion
并制作两个这样的字段
1. comment_id
2.输入(喜欢或不喜欢)
那么,我是否必须运行尽可能多的SQL查询,因为我的页面上有注释,以便为每个注释获取类似和不喜欢的数据。会不会效率低下。我认为我这里有一些困惑。有人可以澄清这一点。
答案 0 :(得分:0)
你有这样的关系方案:
有两种方法可以解决这个问题。第一个,“干净”的是建立你的“喜欢”表,并在适当的列上做“count(*)'s”。
第二个是在每个评论中存储一个计数器,表示有多少向上和向下。 如果要检查,如果特定用户已对评论进行了投票,则只需检查一个条目,您可以轻松地将其作为自己的查询处理,并将它们合并到数据库外部(为此使用查询得到comment_id和用户在特定线程中所做的投票。)
使用逗号分隔列表的方法效率不高,因为如果没有更高的智能或大量的解析字符串就无法解析它。如果你有一个数据库 - 使用它!
(“一个信息 - 一个数据集”!)
答案 1 :(得分:0)
逗号分隔列表违反了atomicity的原则,因此违反了1NF。您将很难保持参照完整性,并且在大多数情况下也需要查询。
以下是以规范化方式执行此操作的一种方法:
这非常clustering - 非常友好:它将属于相同评论的投票分组在一起(同样用于向下投票),使得以下查询非常有效:
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>;
如果数据足够快,请测量实际数据量。如果没有,则对模型进行非规范化并在COMMENT表中缓存总分,并在每次在* _VOTE表中插入或删除新行时使其保持最新状态。
如果您还需要获得特定用户投票的评论,您需要* _VOTE {USER_ID,COMMENT_ID}上的索引,即上面的主/群集键的反向。 1
1 这就是我没有使用一个包含额外字段的VOTE表的原因之一,该字段可以是1(用于向上投票)或-1( for down-vote):使用二级索引cover的效率较低。