Published on

【转载】Typecho数据库设计

Authors

主体结构

单用户博客数据量如何

Typecho的定位是单用户blog系统,在我们设计它的数据库之前有必要对个人博客系统的负载情况做一些评估.我有一个朋友,是一个勤奋的blogger,alexa排名在十万以上,日IP在10w左右.他选择了wordpress作为主要系统,我们知道wordpress系统的一个主页乐观的估计也有20余次查询.但这依然无法阻挡这款程序的流行,在去年对全球top10 blogger所使用的系统调查中,wordpress比其他系统有着明显的优势.很显然,wordpress的负载是可控的.

当我们在设计一个单用户blog系统时,我们要时刻把单用户这三个字放在心上.单用户意味着数据的查询是很集中的,当一个用户页面的访问量比较小时,他几乎感觉不到这多出的几次查询带来多少延迟.而当访问量比较大时,他必然有实力去升级他的系统,而由于单用户系统的查询比较集中,我们可以通过部署文件缓存或者内存对象缓存来达到减轻数据库压力的目的,或者增加数据库数量来达到平滑的系统扩容.因此单用户系统设计重点在于灵活性和结构化,当我们集中地暴露系统瓶颈,从另一个方面也可以集中精力去解决它.

5张表的设计

让我们列举一下一个blog系统需要哪些元素,这样也可以让我们更好地设计数据库表.我们需要文章,评论,分类,链接,用户,现在的blog系统还需要文件,标签,链接分类,多重分类,如果我们考虑到系统的灵活性,我们还需要将所有的可配置选项放到一个表中,类似于wordpress的options表.

让我们来清点一下这些表.

  1. 文章表
  2. 评论表
  3. 文章分类表
  4. 标签表
  5. 链接表
  6. 链接分类表
  7. 文章与分类映射表(一对多)
  8. 文章与标签映射表(一对多)
  9. 配置表
  10. 用户表
  11. 文件表

一共11张表,虽然不是很多但是总觉得还有抽象的余地.当我们仔细观察它们之间的关系后,除了配置表和用户表之外.其它表之间的关系都可以抽象为内容与项目之间的关系(可能是一对一,可能是一对多),比如评论与分类,链接与链接分类.通过这个抽象,我们可以把剩下的表缩减为3个表,那么来看看我们的第二版数据库结构

  1. 内容表
  2. 关系表
  3. 项目表
  4. 配置表
  5. 用户表

根据以上设计以及我们的经验,只需要精心设计内容表和项目表的表结构就可以形成丰富的扩展应用.项目表与内容表的对应,形成了对内容的修饰.由于有了关系表的存在,内容与项目的关系可以是一对一也可以是一对多.

内容与内容,6张表的设计

如果你仔细分析一下上面的设计,你会发现一个隐藏的问题,那就是评论表的定义.显然评论表不可能是项目表,那么他只可能是内容表,但内容与内容之间的关系是我们以上设计中所没有定义的.观察评论与内容的关系

  1. 评论从属于内容,无法单独存在
  2. 评论与内容是多对一的关系,且一条评论只能对应于一个内容
  3. 评论的数量往往比较大,对于访问量比较大的blog,其单篇文章的评论往往要达到上百篇.

根据以上考虑,评论表应该单独形成一个表与内容区分开,且根据常规做法以及速度上的考虑,评论应该用一个保留字段保存其从属内容的主键,以便查询.那么我们的第三版数据库结构就出炉了

  1. 内容表
  2. 关系表
  3. 项目表
  4. 评论表
  5. 配置表
  6. 用户表

梳理我们的设计

让我们来看看内容表可以扩展出来的类型

  • post(文章)
  • draft(草稿)
  • page(页面)
  • link(链接)
  • attachment(文件)

然后再来看看项目表里的类型

  • category(分类)
  • tag(标签)
  • link_category(链接分类)

表以及字段命名

考虑到标准化和国际化的需要,我们在表以及字段设置上应该尽量使用标准名称.而由于使用了一对多的关系映射,在可以预见的地方内容与项目之间都不可能使用联合查询,而是用多次联动查询,来取出多行关联数据.所以内容表与项目表的字段是可以重名的(在联合查询中,重名字段会被覆盖).以下是我对各数据表的命名

  1. 内容表 - contents
  2. 关系表 - relationships
  3. 项目表 - metas (meta的意思为关于什么的什么)
  4. 评论表 - comments
  5. 配置表 - options
  6. 用户表 - users

数据字典

contents表

键名类型属性注释
cidint(10)主键,非负,自增主键
titlevarchar(200)可为空内容标题
slugvarchar(200)索引,可为空内容缩略名
createdint(10)索引,非负,可为空内容生成时的GMT unix时间戳
modifiedint(10)索引,非负,可为空内容生成时的GMT unix时间戳
texttext可为空内容文字
orderint(10)非负,可为空排序
authorIdint(10)非负,可为空内容所属用户id
templatevarchar(32)可为空内容使用的模板
typevarchar(16)可为空内容类别
statusvarchar(16)可为空内容状态
passwordvarchar(32)可为空受保护内容,此字段对应内容保护密码
commentsNumint(10)非负,可为空内容所属评论数,冗余字段
allowCommentchar(1)可为空是否允许评论
allowPingchar(1)可为空是否允许ping
allowFeedchar(1)可为空允许出现在聚合中

relationships表

键名类型属性注释
cidint(10)主键,非负内容主键
midint(10)主键,非负项目主键

metas表

键名类型属性注释
midint(10)主键,非负项目主键
namevarchar(200)可为空名称
slugvarchar(200)索引,可为空项目缩略名
typevarchar(32)可为空项目类型
descriptionvarchar(200)可为空选项描述
countint(10)非负,可为空项目所属内容个数
orderint(10)非负,可为空项目排序

comments表

键名类型属性注释
coidint(10)主键,非负,自增comment表主键
cidint(10)索引,非负post表主键,关联字段
createdint(10)非负,可为空评论生成时的GMT unix时间戳
authorvarchar(200)可为空评论作者
authorIdint(10)非负,可为空评论所属用户id
ownerIdint(10)非负,可为空评论所属内容作者id
mailvarchar(200)可为空评论者邮件
urlvarchar(200)可为空评论者网址
ipvarchar(64)可为空评论者ip地址
agentvarchar(200)可为空评论者客户端
texttext可为空评论文字
typevarchar(16)可为空评论类型
statusvarchar(16)可为空评论状态
parentint(10)可为空父级评论

options表

键名类型属性注释
namevarchar(32)主键配置名称
userint(10)主键,非负配置所属用户,默认为0(全局配置)
valuetext可为空配置值

users表

键名类型属性注释
uidint(10)主键,非负,自增user表主键
namevarchar(32)唯一用户名称
passwordvarchar(32)可为空用户密码
mailvarchar(200)唯一用户的邮箱
urlvarchar(200)可为空用户的主页
screenNamevarchar(32)可为空用户显示的名称
createdint(10)非负,可为空用户注册时的GMT unix时间戳
activatedint(10)非负,可为空最后活动时间
loggedint(10)非负,可为空上次登录最后活跃时间
groupvarchar(16)N/A用户组
authCodevarchar(40)可为空用户登录验证码