喜欢或投票推荐


10

我正在制作一个小程序,用户可以在其中编写帖子或撰写博客。在这些帖子上,其他用户可以像在Facebook中那样喜欢或不喜欢该帖子,或者像在stackoverflow中那样对帖子进行赞或不赞成。我想知道一个常用的良好数据库结构,并且该程序可以有效地使用该结构。我有两个选择

第一

发布:

id   head   message   datepost   likes   dislikes
1     ab    anchdg     DATE      1,2,3   7,55,44,3

以上述方式,id是postid。在“喜欢”列中,1,2,3是喜欢或赞成该帖子或博客的用户的ID。7,55,44,3是不喜欢或不赞成该帖子或博客的用户的ID。

第二

发布:

id    head  message   datepost
1     ab    anchdg     DATE

喜欢:

id    postid    userid
1       1         1
2       2         2

不喜欢:

id    postid    userid
1       1         7
2       1         55

这样,我必须为喜欢和不喜欢创建两个单独的表,以获取帖子的喜欢。这样,表即LikesDislikes将被大量填充。这可能会使表沉重,处理速度变慢。

因此,我想知道哪种更好和更标准的方法来完成此任务?


4
我假设用户不能喜欢不喜欢帖子?如果是这样,我将有一张表用于喜欢和不喜欢,带有BIT列(1代表喜欢,0代表不喜欢)。
dwjv '02

1
或1和-1以获得更简单的总和
jkavalik '16

1
@dwjv在第一个示例中,用户3实际上喜欢不喜欢该帖子。
丹·亨德森

Answers:


20

您面临的问题被称为数据库的“常规形式”,尤其是第一个常规形式。https://en.wikipedia.org/wiki/First_normal_form

具有串联用户ID(第一版)的数据库不是第一标准格式。

请参阅https://en.wikipedia.org/wiki/Database_normalization,以了解通常认为标准化的原因和方式。

在第一个示例中,“用户4不喜欢该帖子”的查询变得复杂。它将必须执行字符串操作,这将不得不考虑副作用和极端情况(用户是唯一的“喜欢”用户,用户是最后一个喜欢的用户,用户位于喜欢的用户字符串的中间)。我会发现这很糟糕。不要这样 使用规范化的设计。

回复:数据库变得沉重

如果您的帖子有4百万个赞,则在数据库设计1中,您将有一行带有“喜欢”列的行,该列的宽度至少为400万个字符(因为您需要使用逗号作为分隔符)。然后,您将必须对四百万个数字宽的字符串执行字符串操作。这是非常糟糕且缓慢的。

另一方面,数据库被设计为处理数百万行。我们的数据库有几亿行,并且count()-运算非常快。非常快。所以不,这不会成为性能瓶颈。

下一个问题将是可读性和可维护性。

例如,告诉我这2条语句的作用:

select count(*)
from posts
inner join likes on posts.postid = likes.postid
where postid = 7

select len(likes) - len(replace(likes, ',', ''))
from posts
where postid = 7

正如我所提到的,如果桌子上有杂物或数十亿个喜欢的东西,那桌子会不会很重?因为表格很快就会被填满,所以要花很多时间来搜索具有杂项记录的表格吗?
Harshit Shrivastava

6
@HarshitShrivastava mysql可以处理数十亿行的简单表,但是可以想象那些十亿(不喜欢)的用户表中的字符串-可能更大并且难以使用。
jkavalik '16

3
@til_b没有直接提及的一件事(但通常通过使用常规形式来暗示)是正确实施的第二个设计将允许底层数据库引擎保持参照完整性,而第一个设计模式则无法做到这一点。从本质上讲,这意味着,如果删除用户4,数据库将清除链接的数据,因为它知道哪些记录取决于用户4记录。第一种设计无法做到这一点,因为数据库不直观地知道如何管理字符串中的关系。
David Antaramian '16

9

第二种方法要好得多,因为您可以轻松添加或删除喜欢/不喜欢。

但是您应该通过使用一个表来表示喜欢或不喜欢来修改第二种解决方案。
“喜欢/不喜欢”表的列应该是id,postid,userid,另外一个应该是“喜欢”或“不喜欢”的值,例如1表示“不喜欢”,-1表示“喜欢”。

将post_id和user_id设置为复合主键,即可正常工作。

表的大小将随着时间的推移而增长。但是其中只有两个实际列。赞/不喜欢的ID和值。postid和userid仅链接到它,并存储在user和post表中。


3
你应该有user_idpost_idvalue在表中。无需单独的id列。
jkavalik '16

3
正如@jkavalik对问题的评论所建议的那样,对于1和-1,喜欢和不喜欢的值可能比1和2更好,因为它可以通过简单的表和来计算总得分,而不是减去从具有“ 1”的行数中得出具有“ 2”的行。
丹·亨德森

@DanHenderson:喜欢的东西-不喜欢的速度可能快于总和。(这就是说,虽然,它也将与1和-1工作。)

如果您又说了2个动作,例如爱与愤怒,您将如何处理?我的意思是说1表示喜欢,-1表示不喜欢,还有2项操作
PirateApp

如果您不想要sum任何东西,则可以将love = 2设置为anger = 3
Julian S
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.