如何针对我的特定情况有效地设计MySQL数据库

时间:2013-03-03 10:56:06

标签: mysql sql database database-design relational-database

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

我已经制作了这两个表

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

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

    那么,我是否必须运行尽可能多的SQL查询,因为我的页面上有注释,以便为每个注释获取类似和不喜欢的数据。会不会效率低下。我认为我这里有一些困惑。有人可以澄清这一点。

2 个答案:

答案 0 :(得分:0)

你有这样的关系方案:

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

第二个是在每个评论中存储一个计数器,表示有多少向上和向下。 如果要检查,如果特定用户已对评论进行了投票,则只需检查一个条目,您可以轻松地将其作为自己的查询处理,并将它们合并到数据库外部(为此使用查询得到comment_id和用户在特定线程中所做的投票。)

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

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

答案 1 :(得分:0)

逗号分隔列表违反了atomicity的原则,因此违反了1NF。您将很难保持参照完整性,并且在大多数情况下也需要查询。

以下是以规范化方式执行此操作的一种方法:

enter image description here

这非常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>;

[SQL Fiddle]

如果数据足够快,请测量实际数据量。如果没有,则对模型进行非规范化并在COMMENT表中缓存总分,并在每次在* _VOTE表中插入或删除新行时使其保持最新状态。

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


1 这就是我没有使用一个包含额外字段的VOTE表的原因之一,该字段可以是1(用于向上投票)或-1( for down-vote):使用二级索引cover的效率较低。