锁定老帖子 主题:从一道面试题想到的论坛数据库设计
精华帖 (7) :: 良好帖 (6) :: 新手帖 (10) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2009-04-08
用户名,email,主页,电话,联系地址,发帖标题,发帖内容,回复标题,回复内容。 每天论坛访问量300万左右,更新帖子10万左右。 请给出数据库表结构设计,并结合范式简要说明设计思路。 这是我看见的百度面试题,以前也在cdsn上面看见过类似的问题,没有仔细想就写了自己的见解和答 案,很可惜我以前的想法是错误的;算是误人子弟阿,郁闷!因此我还是先把和几个朋友讨论的结果和自 己的想法做一个总结,算是弥补我以前想法造成别人曲解的过错; 首先,我们先来分析一下这道面试题:用户名,email,主页,电话,联系地址,发帖标题,发帖内 容,回复标题,回复内容。这些字段可以基本归为三类: 1、用户基本信息:用户名(UserName),email(Email),主页(HomePage),电话(Tel),联系地址 (Address); 2、发帖主题信息:发帖标题(Title),发帖内容(Content); 3、回复信息:回复标题(RTitle),回复内容(RContent); 以上一步有基本开发经验的人都知道,只是对基本的信息进行划分;相信将用户基本信息存放在一 张表内不会有什么好讨论的,我创建一张表叫T_Users,并建立主键UserID,用户基本信息所需要存放的 内容都放置在此表内;那么是应该把发帖主题和回复信息分别创建两张表存放数据呢还是应该存放在一张 表内?字段内容还是比较接近的,因此从数据冗余的角度看,一张表和两张表在此方面的区别并不影响设 计;假设按照大多数论坛的设计思路,将2、3设计成两个表T_Topics和T_Reverts后,再来分析看看是否 合适这里的要求; 现在“每天论坛访问量300万左右,更新帖子10万左右”对这句话进行分析,才是这个面试题的关键 所在。面试题显然要求在操作数据库的性能方面要有更高的要求。而对数据库的操作而言,检索数据的性 能基本不会对数据造成很大的影响(精确查找的情况下),而对表与表之间的连接却会产生巨大的影响, 特别在有巨量数据的表之间;而对数据库的连接也是相当消耗性能的操作(这在ADO.NET的教程中都多次 提醒的);因此对问题的定位基本可以确定:在显示和检索数据时,尽量减少数据库的连接以及表与表之 间的连接; 解决问题的指导性原则找到了,那就来看看,从上面的设计中,有哪一些地方会产生我们提到的表与 表之间的连接;(连接数据库的次数尽量减少到每打开一个页面只连接一次数据库就可以得到所有的数据 )1、用户基本信息中的用户名在发帖主题列表以及打开一个主题查看回复内容时上面会有所显示,需要 在T_Users和其他两张表进行连接;2、在打开一个主题查看回复内容时,需要在T_Topics和T_Reverts之 间进行连接;其他应该是不需要产生表与表之间的连接;按照面试题来推测:T_Users的数据量应该在1万 -10万之间,T_Topics应该在100-1000万之间,T_Reverts应该在1000万-1亿之间;从上面两类连接可以看 出来,T_Users和T_Topics会在列表页面连接一次;T_Users、T_Topics和T_Reverts三张表会连接一次; 我说不上来第一种连接是否可以允许(至少在我开发的系统里面都是允许的),但是另外三张表连接是绝 对不会允许的!特别是T_Topics和T_Reverts两表之间的连接会产生很大的性能损耗,因此需要避免这样 的情况产生。 那怎么样的设计可以避免T_Topics和T_Reverts两表之间的连接呢?前面已经进行了分析:可以考虑 把发帖主题和回复信息存放在一张表(T_Infos)里面,看看是否可以解决这个问题;我们设计一个字段 (Flag)来标记是主题还是回复的内容;设计一个字段(ParentID,主题此字段为ID值)来指定是哪一个 特定主题的回复;在开打回复信息时,只需要按照所知道的主题ID,就可以检索到这个主题的内容以及所 有的回复内容,上面指出的问题就可以解决! 为了性能,我们再一次对T_Users和T_Infos连接对性能的影响进行一下细致的分析,可以通过在 T_Infos表内增加UserName字段来解决和它的连接,这样至少在显示时,性能能够得到保证;但是这样的 设计因为UserName字段是冗余的,因此在用户修改UserName的时候就会产生同步数据的问题,这个需要程 序来进行弥补,并是我们认为用户不会经常性的修改他的用户名这样的前提下; 因此这道面试题的答案应该是设计两张表,用户基本信息表T_Users和内容表T_Infos,这两张表的连 接还是通过UserID,但是T_Infos中增加UserName这个字段来增加性能! 上面的面试题算是分析完了,但是从这道题目的分析中我们可以看出来,这样的设计是建立在“一个 简单的论坛系统”这样的基础上的极端事例,在我们真实的世界中,不太会有很多的人喜欢这样简单的论 坛,而且这样的论坛在扩展性方面会产生很大的限制;这算不算这道题目是应试教育的产物呢?而且在设 计的时候不仅仅是为了适应现在系统的需求还需要提供将来新的要求的变化,因此在实际的开发过程中间 并不推荐使用这道面试题的答案。 ------------------------------------------------- 以上是我转载的文章 注:最近开始开发论坛系统,无意看到这篇文章,希望大家就这篇文章发表自己的想法 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2009-04-08
请大家分享下自己对大型论坛数据库结构设计的经验
不知道JavaEye的论坛是怎么设计的,还是请有经验的人分享下论坛数据库设计经验 小弟不胜感激 |
|
返回顶楼 | |
发表时间:2009-04-09
最后修改:2009-04-10
JE的好像是两张表:主题表和回复表,而且定义了他们之间的关系,然后是使用了大量的缓存。缓存对于设计论坛系统还是有很大优势的。另外Robbin还说了,为了更好的使用缓存,还可以把回复的内容单独提取出来作为一个表。^_^
忘了是robbin是这样说的还是这样设计的。 |
|
返回顶楼 | |
发表时间:2009-04-09
我是不同意冗余的存在的。表面上看起来好像少查了一张表,但是因为帖子数量极大,会因为冗余占用大量的空间。
我觉得如果SQL编写得好的话,未必会造成很大的性能损失。 一个建立系统是系统工程,完全靠数据库扛可不行。这种数据量大,但是对实时和数据绝对安全性要求较低的应用,大量使用缓存的话可以极大提高处理能力。 |
|
返回顶楼 | |
发表时间:2009-04-09
最后修改:2009-04-09
这样的设计能用吗,你把数据查出来之后怎么确定那条数据是主题,哪些是回复呢,再遍历一次?还有就是你这样设计和分成两个表然后做单表查询的差别有多大,多一次查询也不会损失多大的性能吧,而且你这么设计的话,索引怎么建比较好呢,还有就是会不会造成这个表过热,还有……
我觉得如果真的负载很重,还是分表来的更实在些吧,另外,我同意猫咪的观点,像论坛这样的系统,使用缓存可以大大降低数据库的负载 |
|
返回顶楼 | |
发表时间:2009-04-09
wendong007 写道 这样的设计能用吗,你把数据查出来之后怎么确定那条数据是主题,哪些是回复呢,再遍历一次?还有就是你这样设计和分成两个表然后做单表查询的差别有多大,多一次查询也不会损失多大的性能吧,而且你这么设计的话,索引怎么建比较好呢,还有就是会不会造成这个表过热,还有……
我觉得如果真的负载很重,还是分表来的更实在些吧,另外,我同意猫咪的观点,像论坛这样的系统,使用缓存可以大大降低数据库的负载 可以用一个字段标志是主题还是回复 |
|
返回顶楼 | |
发表时间:2009-04-09
问题多多。
|
|
返回顶楼 | |
发表时间:2009-04-09
tangmi 写道
wendong007 写道
这样的设计能用吗,你把数据查出来之后怎么确定那条数据是主题,哪些是回复呢,再遍历一次?还有就是你这样设计和分成两个表然后做单表查询的差别有多大,多一次查询也不会损失多大的性能吧,而且你这么设计的话,索引怎么建比较好呢,还有就是会不会造成这个表过热,还有……
我觉得如果真的负载很重,还是分表来的更实在些吧,另外,我同意猫咪的观点,像论坛这样的系统,使用缓存可以大大降低数据库的负载 可以用一个字段标志是主题还是回复
那你是查询一次还是两次呢,如果查询两次的话,放在一个表里还有什么意义,如果查询一次,那岂不是查询完毕之后还有遍历一次所有结果条目,检查你设定的标记以判断是回复还是主题贴? |
|
返回顶楼 | |
发表时间:2009-04-09
大家的意思是分成主题表、回复表等多个表?
还是合成一个表然后做物理分区? 哪种更好呢? |
|
返回顶楼 | |
发表时间:2009-04-09
wendong007 写道 这样的设计能用吗,你把数据查出来之后怎么确定那条数据是主题,哪些是回复呢,再遍历一次?还有就是你这样设计和分成两个表然后做单表查询的差别有多大,多一次查询也不会损失多大的性能吧,而且你这么设计的话,索引怎么建比较好呢,还有就是会不会造成这个表过热,还有……
我觉得如果真的负载很重,还是分表来的更实在些吧,另外,我同意猫咪的观点,像论坛这样的系统,使用缓存可以大大降低数据库的负载 再这么高插入更新的频率下 索引就有些不实用了,创建索引会降低插入更新的速度而且访问量这么大的情况下,索引不建议采用 |
|
返回顶楼 | |