标点符(钱魏 Way)

Typecho的数据库设计的学习

Typecho是一款仿Wordpress,但相对Wordpress要简单的多的开源博客程序。开发者大量的参考了WordPress的设计,去除了一些高级复杂的功能,实现了一个小而美的博客系统。它的优点:

  • 轻量高效:仅仅 7 张数据表,加上不足 400KB 的代码,就实现了完整的插件与模板机制。超低的 CPU 和内存使用率,足以发挥主机的最高性能。
  • 先进稳定:原生支持 Markdown 排版语法,易读更易写。支持 BAE/GAE/SAE 等各类云主机,即使面对突如其来的高访问量,也能轻松应对。
  • 简洁友好:精心打磨过的操作界面,依然是你熟悉的面孔,更多了一份成熟与贴心。每一个像素的剪裁,都只为离完美更进一步。

一起来看下7张表的数据库的数据库设计,看从中能学到什么。

Typecho数据库设计

设计思路

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

5张表的设计

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

  • 文章表
  • 评论表
  • 文章分类表
  • 标签表
  • 链接表(友情链接)
  • 链接分类表
  • 文章与分类映射表(一对多)
  • 文章与标签映射表(一对多)
  • 配置表
  • 用户表
  • 文件表

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

  • 内容表
  • 关系表
  • 项目表
  • 配置表
  • 用户表

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

6张表的设计

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

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

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

  • 内容表
  • 关系表
  • 项目表
  • 评论表
  • 配置表
  • 用户表

梳理设计

内容表可以扩展出来的类型

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

项目表里的类型

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

表以及字段命名

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

  • 内容表 – contents
  • 关系表 – relationships
  • 项目表 – metas (meta的意思为关于什么的什么)
  • 评论表 – comments
  • 配置表 – options
  • 用户表 – users

Typecho数据字典

contents表

键名 类型 属性 解释
cid int(10) 主键,非负,自增 post表主键
title varchar(200) 可为空 内容标题
slug varchar(200) 索引,可为空 内容缩略名
created int(10) 索引,非负,可为空 内容生成时的GMT unix时间戳
modified int(10) 非负,可为空 内容更改时的GMT unix时间戳
text text 可为空 内容文字
order int(10) 非负,可为空 排序
authorId int(10) 非负,可为空 内容所属用户id
template varchar(32) 可为空 内容使用的模板
type varchar(16) 可为空 内容类别
status varchar(16) 可为空 内容状态
password varchar(32) 可为空 受保护内容,此字段对应内容保护密码
commentsNum int(10) 非负,可为空 内容所属评论数,冗余字段
allowComment char(1) 可为空 是否允许评论
allowPing char(1) 可为空 是否允许ping
allowFeed char(1) 可为空 允许出现在聚合中

relationships表

键名 类型 属性 解释
cid int(10) 主键,非负 内容主键
mid int(10) 主键,非负 项目主键

metas表

键名 类型 属性 解释
mid int(10) 主键,非负 项目主键
name varchar(200) 可为空 名称
slug varchar(200) 索引,可为空 项目缩略名
type varchar(32) 可为空 项目类型
description varchar(200) 可为空 选项描述
count int(10) 非负,可为空 项目所属内容个数
order int(10) 非负,可为空 项目排序

comments表

键名 类型 属性 解释
coid int(10) 主键,非负,自增 comment表主键
cid int(10) 索引,非负 post表主键,关联字段
created int(10) 非负,可为空 评论生成时的GMT unix时间戳
author varchar(200) 可为空 评论作者
authorId int(10) 非负,可为空 评论所属用户id
ownerId int(10) 非负,可为空 评论所属内容作者id
mail varchar(200) 可为空 评论者邮件
url varchar(200) 可为空 评论者网址
ip varchar(64) 可为空 评论者ip地址
agent varchar(200) 可为空 评论者客户端
text text 可为空 评论文字
type varchar(16) 可为空 评论类型
status varchar(16) 可为空 评论状态
parent int(10) 可为空 父级评论

options表

键名 类型 属性 解释
name varchar(32) 主键 配置名称
user int(10) 主键,非负 配置所属用户,默认为0(全局配置)
value text 可为空 配置值

users表

键名 类型 属性 解释
uid int(10) 主键,非负,自增 user表主键
name varchar(32) 唯一 用户名称
password varchar(32) 可为空 用户密码
mail varchar(200) 唯一 用户的邮箱
url varchar(200) 可为空 用户的主页
screenName varchar(32) 可为空 用户显示的名称
created int(10) 非负,可为空 用户注册时的GMT unix时间戳
activated int(10) 非负,可为空 最后活动时间
logged int(10) 非负,可为空 上次登录最后活跃时间
group varchar(16) N/A 用户组
authCode varchar(40) 可为空 用户登录验证码

参考链接:

码字很辛苦,转载请注明来自标点符《Typecho的数据库设计的学习》

评论

  1. #1

    你好想请教你关于标签 分类 建表 一对多的 数据怎么处理

    回复
    2017-03-3