13
回答
为什么数据库表要用一对一的关系? 有什么好处.
利用AWS快速构建适用于生产的无服务器应用程序,免费试用12个月>>>   

下面是jForum论坛的两张数据库表, 第一张表是帖子的一些属性, 第二张表是帖子的内容, 两张表是一对一的关系.

我不明白为什么要用一对一的关系, 直接放在一张表里不好吗? 这样只操作一张表, 很好维护.

一对一的关系有什么好处?难道是把大字段单独存可以提高查询性能吗?

CREATE TABLE jforum_posts (
  post_id INT NOT NULL auto_increment,
  topic_id INT NOT NULL default '0',
  forum_id INT NOT NULL default '0',
  user_id INT NOT NULL default '0',
  post_time datetime default NULL,
  poster_ip varchar(15) default NULL,
  enable_bbcode tinyint(1) NOT NULL default '1',
  enable_html tinyint(1) NOT NULL default '1',
  enable_smilies tinyint(1) NOT NULL default '1',
  enable_sig tinyint(1) NOT NULL default '1',
  post_edit_time datetime default NULL,
  post_edit_count INT NOT NULL default '0',
  status tinyint(1) default '1',
  attach TINYINT(1) DEFAULT '0',
  need_moderate TINYINT(1) DEFAULT '0',
  PRIMARY KEY  (post_id),
  KEY (user_id),
  KEY (topic_id),
  KEY (forum_id),
  KEY(post_time),
  INDEX (need_moderate)
) TYPE=InnoDB;

CREATE TABLE jforum_posts_text (
    post_id INT NOT NULL PRIMARY KEY,
    post_text TEXT,
    post_subject VARCHAR(100)
) TYPE=InnoDB;

 

举报
songerjun
发帖于7年前 13回/8K+阅
共有13个答案 最后回答: 7年前

哎呀呀,把标题也抽出来了,确实值得一学。

一看第一张表,已经服了,高手调整过的表啊。好处太多了,简单说几个:

1、第一张的表结构,在IO存储的时候,每行数据都是等长的,这个表的设计真的花了心思了。唯独:poster_ip varchar(15),其实ip也可以用整型。

2、第二张表第一个特点,post_id不是自增的,自增主键是要靠锁表产生新的主键值的。所以,这个表不存在这个自增约束的问题。很早以前做过测试,有自增和无自增的条件下,插入速度会有很大的差别。但post_id其实可以做一个索引。

3、第一张表实际上是状态表,帖子的状态随时在变,第1、已经说了,由于其在IO存储时的特性,决定了这个表在读写方面有一定优势。

4、内容分离,这个大家都说了。内容分离还有好处,在做数据索引等外围操作的时候,速度会更好。内容分离其实对于审查等,也十分方便。不过内容分离造成了代码在逻辑上的复杂度。

MySql在百万级的时候,只要看配置和表优化良好,一般查写还不会有太大的问题(我试过用MyISAM做Session表,上千万了,就是查询会缓慢,不过还能插新session,当然,这时应该做得事情就是清空session表)。但他InnoDB,要用事务回滚,是为了防止关联操作时发生数据异常。MyISAM作为log应用,是非常强大的。InnoDB做第二张表,我还是会有些惊。其实可以加个last_modify字段,内容表是允许冗余的,只要通过检查last_modify就能拿出有效的数据了。日常管理,检查post_id出现冗余的字段进行清空即可了。这样第一张表操作开事务,第二张写入异常则食物回滚,不然就commit。

其实还是有可以优化的地方的,我喜欢将日期时间等都用整型处理,这样做表转移也会简易很多。当然,个人习惯。

难道是把大字段单独存可以提高查询性能吗?

把大字段单独存储有个好处,在读帖子列表的时候,无需读取内容,可以降低数据库的压力

引用来自#2楼“红薯”的帖子

难道是把大字段单独存可以提高查询性能吗?

把大字段单独存储有个好处,在读帖子列表的时候,无需读取内容,可以降低数据库的压力

可是帖子列表也需要标题, 标题在第二张表中, 也是需要读第二张表的.

而且放在一张表中也可以不用全部都读出来.

大字段单独存储还有一个好处就是:当表内数据达到10万,100万时,如果添加一个字段或修改一下字段时,不会造成锁表!

谢谢楼上的, 可能仅仅是设计时考虑的角度不同, 我刚刚看了discuz的表, 是放在同一张表中的. discuz的性能还是比较好的, 不过discuz是用的MyISAM引擎, jForum是用的InnoDB引擎

在数据量小的时候, 数据表怎么做都可以,基本上是 "表结构" 围绕 "功能" 来设计.

一但数据量大了, 数据库很容易成了系统的瓶颈,  这个时候就需要对数据库有一个好的规划,

比如: 索引设计,储存引擎的选择, 数据表的切分(水平/垂直), 读写分离,甚至是数据库集群.

你上面的例子是属于"数据表垂直切分", 主要优点是更新/插入是可以减小锁表时间, 查询时可以减小读取的数据量. 如果把两个表文件保存在不同的硬盘上, 那么查询的性能可以更高.

当然,如果数据切分得不合理, 性能反而更差.

discuz的表也是把topic和content分开的,topic相当于快照表,论坛首页遍历帖子用这个,另外discuz还做了一个自动分表的,都是为了提高效率

引用来自#4楼“Jimmy”的帖子

大字段单独存储还有一个好处就是:当表内数据达到10万,100万时,如果添加一个字段或修改一下字段时,不会造成锁表!

为什么达到10万或100万时添加或修改会造成锁表呢?

引用来自#2楼“红薯”的帖子

难道是把大字段单独存可以提高查询性能吗?

把大字段单独存储有个好处,在读帖子列表的时候,无需读取内容,可以降低数据库的压力

大叔此言差矣! 我又不 select * 怎么会查询到内容呢, select title 不就OK了吗

顶部