MYSQL 评论表结构优化

2018-05-02 16:40:04 +08:00
 Aluhao

数据表结构

CREATE TABLE comments (

id bigint(20) unsigned NOT NULL AUTO_INCREMENT,

aid bigint(20) unsigned NOT NULL DEFAULT '0',

uid bigint(20) unsigned NOT NULL DEFAULT '0',

contents text NOT NULL,

likes int(10) unsigned NOT NULL DEFAULT '0',

comments int(10) unsigned NOT NULL DEFAULT '0',

time int(10) unsigned NOT NULL DEFAULT '0',

PRIMARY KEY (id),

KEY aid (aid),

KEY time (time)

) ENGINE=MyISAM DEFAULT CHARSET=utf8;

现在有 7 千万数据, 表大小 3.60 GB 索引大小 2.55 GB ; AID 是新闻的 ID ; UID 是评论用户; contents 是评论内容; 随着数据越来越多表越来越大,如果分表,业务逻辑很麻烦,又达不到需求,有什么好的优化方案?

我现在想把 contents 内容单独一个表存放,就是说这个评论表 增加一个表;

CREATE TABLE comments_data (

id bigint(20) unsigned NOT NULL DEFAULT '0',

contents text NOT NULL,

PRIMARY KEY (id)

) ENGINE=MyISAM DEFAULT CHARSET=utf8;

这样虽然能优化一些,但终究不是最终解决方案,不知道 V2 朋友们有没做过类似的数据结构优化;

7661 次点击
所在节点    MySQL
44 条回复
jetyang
2018-05-02 20:14:15 +08:00
分表,按 aid 分表
likes、comments 看上去是收藏数和评论数,如果经常更新建议拆出去
Leigg
2018-05-02 20:32:06 +08:00
兄 dei,首先你这个肯定要做缓存的,至少把最近一周或一个月的新闻的评论放到缓存服务器上,至于分表的话我建议做水平分表,垂直分没什么作用,毕竟查的是评论这种占空间的文本内容。最后我想说你的这种结构用 mongo 很好做,mongo 可以把一条新闻下的所有用户的评论存为一条记录,算起来这个记录数怕不是要比 mysql 少多少倍。。
sheldoner
2018-05-02 20:48:45 +08:00
@Leigg 请教一下 “ mongo 可以把一条新闻下的所有用户的评论存为一条记录” 所有评论怎么存为一条记录
Aluhao
2018-05-02 20:49:30 +08:00
@Leigg 是呀,求方法
qiayue
2018-05-02 21:19:23 +08:00
@sheldoner @Aluhao mongo 存的是 bjson 文档,可以简单理解为 json 格式数据,把所有评论放到一个 json 里不就是一条记录么
xudaiqing
2018-05-02 21:21:39 +08:00
MySQL 不是很熟,但我记得 MyISAM 各方面都不如 Innodb 而且已经几乎停止开发了。
3.60 GB 数据量很小,一般的索引就够了。如果性能不行,内存太小或者索引和查询的设计有问题的的可能性比较大。
索引大小 2.55 GB 感觉太大了,我觉得索引可能有问题。
“索引虽然只建了 id 和 aid 二个” 对 id 建索引意义何在?
Leigg
2018-05-02 21:46:46 +08:00
@sheldoner 酱紫的,类 json 格式存储一条新闻下的所有评论,
{新闻 id:xxx, 评论数:xxx, 评论信息:[ {
评论 id:xxx,
评论文本:xxx,
评论用户:xxx,
回复楼层:xxx,
赞数:xxx,
},{},{} ]
}
评论信息的 value 按评论楼层排序,这是 mongo 中大概的字段设计模型,具体怎么设计要看业务需求。但肯定比 mysql 快,索引也省不少空间。楼主可以当做参考哈~
iyaozhen
2018-05-02 21:55:03 +08:00
几亿以下的数据都可以考虑表分区,按照 aid 或者时间分区,where 条件带上分区字段,索引正确很快。主要是业务代码不需要改动
然后数据库建议升级到 5.7 或者 8.0,使用 innodb
hwiiago
2018-05-02 22:08:51 +08:00
水平分表、mongo、缓存、冷热分离、#7 楼 es 方案,视具体业务场景选择。
kran
2018-05-02 22:51:16 +08:00
单文章评论不会急剧增长,应该考虑按照评论数分表,比如一千万。文章表存储评论表 id,新建文章时确定评论表 id,如果最大 id 评论表存储的数目大于一千万,就增一并新建相应评论表。完全不需要引入其他依赖。
blueskit
2018-05-02 23:05:13 +08:00
数据量不大应该并不迫切分表什么的。
建议从查询日志分析具体的慢查询类别、然后对症下药。
不管怎么说,加缓存可以先上
msg7086
2018-05-02 23:19:26 +08:00
@xudaiqing 主键索引。
xudaiqing
2018-05-03 06:34:21 +08:00
@msg7086 主键是自动强制索引的,单独拿出来说就怕是 id 的常规索引
very9527
2018-05-03 09:07:18 +08:00
content 的字段是不是太大了?
enhancer
2018-05-03 09:50:14 +08:00
@Aluhao 那就应该考虑根据评论表中的 [新闻 ID] 来分表,确保某条新闻,根据其新闻 ID 加载的评论都全部来自某张评论分表。
sheldoner
2018-05-03 11:59:08 +08:00
@qiayue 谢谢,我们用的是 redis,没太关注 mongo 的文档
@Leigg 像这样的话,系统启动,评论信息就初始化到 mongo 里面了。评论的东西感觉也有很大了,这样初始化,mongo 性能够吗,内存占用也会很高吧
Leigg
2018-05-03 13:26:36 +08:00
@sheldoner 可以通过配置“缓存大小”来优化,数据量到一定级别后且高并发查询和写入的话要做副本集或分片,像题主这种情况不至于高并发写入,做副本集应该足以应对。但是做分片可以避免单台实例过于臃肿的情况。
MeteorCat
2018-05-03 13:31:53 +08:00
@sheldoner mongo 不是什么灵丹妙药,大量数据加载进 mongo 之后内存很快吃光了,如果并发量并不是那么高[比如有的内容仅仅三五个人看一遍没必要上 mongo],本地文件读取都行;还有另外一种优化方法,就是加载渲染内容的时候不一起加载评论[这也是一个普遍做法],评论另外走 js 接口拼接到内容下面,判断用户是否拉到最下面准备读取评论
houshengzi
2018-05-03 13:53:06 +08:00
觉得应该优先考虑 MySQL partition
sheldoner
2018-05-03 14:23:50 +08:00

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/451509

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX