问题的引出
一个简单的论坛系统,以数据库储存如下数据:
用户名,email,主页,电话,联系地址,发帖标题,发帖内容,回复标题,回复内容。
每天论坛访问量300万左右,更新帖子10万左右。
请给出数据库表结构设计,并结合范式简要说明设计思路。
只是对问题的一点总结和自己的一些看法,原问题的论坛链接http://www.iteye.com/topic/364016,一个方案http://blog.youkuaiyun.com/zou274/article/details/4091036
论坛上一个人参考对问题的分析(主要看思路,不一定是最合理,感觉有时候还要看你的硬件配置是什么样的)
问题分析: 每天论坛访问量300万左右,更新帖子10万左右。
1. 读写比例在30:1左右, 应向读取效率方面倾斜. 索引建立需参考常用读取的主关键字.
2. 每月数据在10W*30=300W. 可按月分表
结构:
用户信息:独立表,userid主键
发帖、回帖(两个表,可以满足个性化的需求,否则要一直的加字段,有冗余):按月表存储,帖子唯一ID主键,日期索引。
帖子内容明细:按月存储,帖子唯一ID主键
综合起来主要有以下几点
1.分表
简单原理就是先算在查,跟海量数据中hash分类差不多,可以根据id来判断,或者时间判断是在哪个表的里面。分区能提高查询效率,但是分区要降低插入效率。无论你拿多少记录(甚至是1条), 如果两个大表关联都可能会产生非常大的中间值, 如果你排序(排序字段没有用到索引), 你都可能导致数据库采用各种各样的方式来计算。水平分表可以解决这个问题, 只要你能保证每个表只存适合的记录数(例如100W一个表) (水平分区也可以解决IO的一些问题)。还有可切分数据库如下:
垂直切分:用户库、主题库、回复库
水平切分:用户库1-n、主题库1-n、回复库1-n
2.索引
对于一个实时的在更新的论坛,建立索引的话会因为维护索引而大大的降低性能(10w条,不足以影响性能),如果不建立索引查询的速度性能可能会差。倾向于使用索引,理由如下
1)读和写的比例相差很大,用户体验当然是读多写少,所以综合考虑还是要用索引,而且是加在常用的读关键字上。
2)索引之所以会降低更新的速度的速度,是因为在更新完对应字段后还需要更新对应字段的索引。我们回到题目中,看到更新帖子10万左右。 这句话是说,我们可能对发帖标题,发帖内容,回复标题,回复内容这4个字段做更新。
3.缓存
生成静态页(把首页类似的什么先读出来放到一个静态页面里面),或者缓存最新最热的帖子。建立主题缓存表(这个取每个区的前面100条记录),一般来说负载最大的就是主题的第一页,所以缓存表是个小表(静态页面是对主题缓存表的进一步)。总之就是缓存常用的页面和数据。
4.避免表扫描(表链接)
可以先读取主题,在按照主题ID读取回复;再按照用户ID读取用户;而不要使用关联,关联对数据库的影响也是很大的(需要表的扫描)。引用论坛上一句“使用关联不如多次使用主键查询来的快”。
5.读写分离
用主从数据库,master是写, slave是读 。
6.其他一些方案
1)在数据库和用户之间建立一个缓冲区。(如,将更新的数据放到内存中,达到一定数量的时候再统一更新数据库。假如以100条为例,一旦内存中达到100条数据量将这100条数据统一入库。减少insert操作)
2)写方面,估计主要是INSERT吧,这个可以异步操作的。所有的写贴操作放到一个队列然后批量执行插入数据库操作,也是缓存思想。
3)在前端表现上,可以使用ajax等方式,分步骤取数据,比如主贴的内容先取出来,然后再逐步加载回复信息等。