原文连接:数据库
http://blog.csdn.net/ztchun/article/details/71106117json
评论功能已经成为APP和网站开发中的必备功能。本文主要介绍评论功能的数据库设计。缓存
评论功能最主要的是发表评论和回复评论(删除功能在后台)。评论功能的拓展功能体现有如下几方面:
(1)单篇文章的评论数量和信息展现;
(2)从时间维度,按照时间倒叙的方式展现动态的用户评论信息;
(3)不一样栏目,不一样模块,不一样时间维度的评论排行展现;
(4)精华评论的单独推荐和聚合展现;
(5)评论后直接分享到绑定的第三方平台;
(6)点赞数、回复数等维度的排行等。微信
评论的后台管理:
(1)删除;
(2)推荐;
(3)精华;
(4)屏蔽,敏感关键字的库的完善、自动屏蔽或者替换功能。闭包
本篇文章主要分析几种客户端评论数据表的设计。数据库设计
(1)需求分析性能
大部分APP采用简单的评论设计便可,便是一问一答模式,好比微信朋友圈的评论功能的设计。如:优化
A:今每天气真好! B @ A :今每天气确实不错!
这种设计简单、直接,也知足了用户评论、回复的基本要求,对于没有大量用户评论的APP需求足够。网站
(2)数据库设计
这种场景下通常评论较少,评论不活跃,能够不区分评论和回复,统一当作评论。区别是,有些评论是直接评论主题,而有些是@其余用户,使用一张表就能够达到效果,评论表设计以下:ui
表字段 | 字段说明 |
---|---|
id | 主键 |
topic_id | 主题id |
topic_type | 主题类型 |
content | 评论内容 |
from_uid | 评论用户id |
to_uid | 评论目标用户id |
topic_type:为了能复用评论模块,咱们引入这个字段来区分主题的类别。
from_uid:表示评论人的id,经过该id咱们能够检索到评论人的相关信息。
to_uid 是评论目标人的id,若是没有目标人,则该字段为空
出于性能的考虑,每每咱们会冗余评人的相关信息到评论表中,好比评论人的nick、头像,目标用户也是如此。 这样一来咱们就只用查询单表就能够达到显示的效果
有时,目标用户有多个,那么能够将to_uid字段修改成to_uids,保存时用分隔符来分割用户id,而目标用户的信息再去查询缓存或者数据库。也能够简单的将多个目标用户的信息一块儿存成json格式,能够应付简单的展示需求。
(1)需求分析
若是以评论为主的显示模式,相似于下面的CSDN的评论显示模式:
这里将评论分为评论和回复,全部评论均挂在评论下面,相似于树状结构。
(2)数据库设计
在以评论为主的树形显示状况下,数据库的设计十分灵活,可使用单表,添加一个parent_id字段来指向父评论,须要嵌套查询。
同时也能够将评论拆分为评论表和回复表,评论挂在各类主题下面,而回复挂在评论下面。
评论表设计以下:
表字段 | 字段说明 |
---|---|
id | 主键 |
topic_id | 主题id |
topic_type | 主题类型 |
content | 评论内容 |
from_uid | 评论用户id |
回复表设计:
表字段 | 字段说明 |
---|---|
id | 主键 |
comment_id | 评论id |
reply_id | 回复目标id |
reply_type | 回复类型 |
content | 回复内容 |
from_uid | 回复用户id |
to_uid | 目标用户id |
因为咱们拆分了评论和回复,那么评论表就再也不须要目标用户字段了,由于评论均是用户对主题的评论,评论表的设计更佳简洁了。
回复表添加了一个comment_id字段来表示该回复挂在的根评论id,这样设计也是出于性能方面的考虑,咱们能够直接经过评论id一次性的找出该评论下的全部回复,而后经过程序来编排回复的显示结构。 经过适当的冗余来提升性能也是经常使用的优化手段之一。
reply_type:表示回复的类型,由于回复能够是针对评论的回复(comment),也能够是针对回复的回复(reply), 经过这个字段来区分两种情景。
reply_id:表示回复目标的id,若是reply_type是comment的话,那么reply_id=commit_id,若是reply_type是reply的话,这表示这条回复的父回复。
(1)需求分析
这种场景中评论和回复是同级显示的,回复不在显示结构上不用挂在一个评论下面。 双表的设计在这里就不太合适了,由于涉及到评论和回复的混排,使用双表则会致使查询的逻辑过于复杂。 因此建议仍是采用单表的设计,不区分评论和回复会简化应用层的逻辑。 咱们统一都当作评论,而有些评论是能够引用其余评论的。
(2)数据库设计
本人推荐采用闭包表的设计,例如:
comment表设计:
表字段 | 字段说明 |
---|---|
id | 主键 |
topic_id | 主题id |
topic_type | 主题类型 |
content | 评论内容 |
from_uid | 评论用户id |
parent_child表:
表字段 | 字段说明 |
---|---|
id | 主键 |
parent_id | 父id |
child_id | 子id |
comment表保存全部评论内容,而parent_children表则记录评论表中各个评论的父子关系。
查询时每每会按照时间排序,咱们能够直接按id或者建立时间降序排列查询comment表便可。 若是用户想查询一条评论的完整引用,则能够经过parent_children来找到对应的路径。
闭包表在查询时很是方便,可是插入的性能稍差,由于除了插入评论表之外,还须要把该条评论全部的父子关系插入到父子关系表中。 插入性能会随着评论层级的加深而线性降低。
若是你的系统天天都会拥有成千上万条评论,那么单表的设计确定是不行,优化的方式有如下几种思路。
(1)分库分表。 分库分表是最为经常使用也最有效的优化方式,建议按照主题来分库分表。 这样同一个主题下面的评论就会落到同一张表里,避免了跨表查询。
(2)适当的数据冗余。 若是你须要显示评论人的相关信息,那么在插入评论时就把这些信息写入评论表中,避免屡次查询。 实际上,若是是纪录数据,均可以冗余对应的数据信息,由于它们的数据的实时行和一致性要求并不高。
(3)附加幂。数据只容许单项操做。 由于从幂性的要求来讲,每一个赞全都是一条记录。 评论的赞数若是都从点赞表中统计得出,那么性能开销会十分巨大,并且点赞如此轻量级的一个操做必定会加重点赞表的竞争操做。 因此建议直接在评论表中添加一个like_count的计数器,该字段只增不减。客户端,能够设置取消效果。
(4)热门评论加缓存。 相似于网易新闻的热门评论,读取频度很是高,能够专门开接口作缓存。