文档章节

mysql web数据库的设计归范-2表设计原则

董泽润
 董泽润
发布于 2014/07/11 15:37
字数 1934
阅读 616
收藏 17

[职责分离原则]

职责分离原则是指在设计的时候应当考虑到数据的产生,聚合使用等原则,每个系统干自己能干的事情,每个系统只干自己的事情。一个数据表应该放在哪个系统中,通常取决于几点:

1. 谁产生这个信息:通常情况下谁产生了这个数据应当对此数据负责;也就是考虑该数据的创建,发展,销毁等全生命周期的定义,并将这个定义维护起来提供给消费者作为消费原则;

2. 谁最经常使用这个信息:如果某个系统最经常使用这个数据,最经常去修改某个数据,也应该由该系统来负责保存维护该数据;

3. 遵守高内聚,低耦合的考虑:在存放数据的时候如果考虑到数据使用原则导致了相关度非常高的数据存放在多个地方,需要多个系统来维护这个数据就有可能导致系统间的耦合性增强,应当尽量避免。

在我们设计数据库表间的关系的时候也应当遵守相同原则,职责分离降低耦合,但同时要考虑到性能情况,做到适当冗余而不导致修改逻辑复杂。

举个最常见贴子与评论的例子:

CREATE TABLE `wanted_post` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `puid` int(10) unsigned NOT NULL,
  `user_id` int(10) NOT NULL COMMENT '发贴用户的id',
  `username` varchar(50) NOT NULL COMMENT '发贴用户的用户名',
  `city` smallint(4) NOT NULL COMMENT '所在城市',
  `ip` bigint(14) NOT NULL COMMENT '发帖人的ip',
  `district_id` tinyint(2) NOT NULL COMMENT '所在区域的id',
  `district_name` varchar(20) NOT NULL COMMENT '行政区名字',
  `street_id` tinyint(2) NOT NULL COMMENT '所在街道(地标)的id',
  `street_name` varchar(20) NOT NULL COMMENT '小区名字',
  `title` varchar(255) NOT NULL COMMENT '帖子的标题',
  `description` text NOT NULL COMMENT '帖子详情描述',
  `post_at` int(11) NOT NULL COMMENT '用户发帖时间,数据创建的时间,使用整型存储',
  `refresh_at` int(11) NOT NULL COMMENT '帖子被修改的时间,整型存储',
  `show_time` int(11) NOT NULL COMMENT '帖子显示时间',
  `age_max` int(11) NOT NULL DEFAULT '0' COMMENT '招聘最小年龄',
  `age_min` int(11) NOT NULL DEFAULT '0' COMMENT '招聘最大年龄',
  `post_refresh_at` int(11) NOT NULL COMMENT '刷新时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `idx_puid` (`puid`),
  KEY `user_id_index` (`user_id`),
  KEY `post_at_index` (`post_at`),
  KEY `refresh_at_index` (`refresh_at`),
  KEY `show_time_index` (`show_time`)
) ENGINE=InnoDB AUTO_INCREMENT=55295 DEFAULT CHARSET=utf8 COMMENT='招聘帖子表'


CREATE TABLE `wanted_post_comment_99` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `puid` int(10) unsigned NOT NULL,
  `user_id` int(10) NOT NULL COMMENT '评论用户ID',
  `post_at` int(11) NOT NULL COMMENT '评论时间',
  `detail` text NOT NULL COMMENT '评论详情',
  PRIMARY KEY (`id`),
  KEY `user_id_index` (`user_id`),
  KEY `puidid_index` (`puid`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8 COMMENT='招聘评论分表99'


由于评论表数据量很大,在预先做好分表,按贴子puid分成100张子表,那么当前详情页涉及sql如下:

select * from wanted_post where puid=xxxx;
select * from wanted_post_comment_99 where puid=xxxx;

这是一个简化的模型,评论多了,还要涉及分页,不可能一次性全取出来。对于上面的场景,严格尊守高内聚,低耦合的原则,不会存储冗余数据。相比较还有一种文档型数据库,例如mongo,就可以将评论与贴子存放在一起,访问的时候只需一次顺序IO操作。整体来讲表设计,要按照职责划分原则。


[在线处理与分析分离]

1. 为了保障线上数据处理的性能,将一些分析相关的数据及分析结果,应当使用单独的库来进行存储,避免在数据分析的时候导致业务数据吞吐量下降,引起系统问题。

2. 专门用于存放离线报表数据,并提供线上数据查询方法,建议将统计结果,汇总的数据都从在线处理数据库中移走。



对于上面的wanted_post求职贴子表,在线处理只能是用户在操作:浏览,修改,删除,分别对应如下sql:

select * from wanted_post where puid=xxxxx;
update wanted_post set xxx=xxx where puid=xxxx;
delete from wanted_post where puid=xxxx;


同样,对于后台统计来讲,都是些聚合操作,非常消耗性能,例如查看某一用户发贴量:

select count(*) from wanted_post where user_id=xxxx;

上面举个通用的例子,原则上要将在线用户请求和后台统计请求分开。简单来讲,对于这种需求处理如下:

  1. 将请求指向不同slave ,这种方法简单高效,缺点是数据量增大就玩不转。

  2. 建立离线报表库,专门存放统计结果,这样将计算与展示异步处理,缺点是对于实时业务响应不好。

  3. 实时拉取mysql row binlog,做数据的异构处理(tungsten, canal),将增量结果处理后(storm),保存在数据库中,基本实时。


[事务与日志分离]

用户生成内容和用户行为日志要分开,这一点很好理解,举两个例子:

  1. 游戏DB里存放玩家的基础信息,装备,属性,好友列表等等,这些放到数据库里面。但是玩家的行为日志,比如消耗金币,今天下过哪些副本,买过什么顶级装备,这些属于行为日志,应该单独存放并分析处理。 

  2. 对于web用记,有好多用户置顶,刷新,竞价,展示等行为,要求实时并且量很大,一定要和贴子分开。

行为日志,需要做分析处理,并且由于时效性不宜存储在mysql中,后期维护就是地雷。


[历史可追溯]

在数据库设计的时候为了保障数据是可追溯的,应当遵循一些简单的约定,事后方便数据的查询和统计:

1. 对于状态数据,应当设计相应状态的字段来保存该数据的最后状态,同时记录下来该数据的初始创建人,时间以及该数据的最后修改人和修改时间;所以在交易数据(如订单合同),广告数据,账户表等都应该默认有状态(status),创建人(creator/creator_name),创建时间(created_at),最后修改人(modifier/modifier_name),最后修改时间(modified_at)等字段用来表明数据的当前状态,创建信息及修改信息。

2. 针对需要跟踪每次修改的数据,需要在数据发生变化的时候记录一张日志表,用于记录该数据发生变化的全生命周期。针对只需要关注关键字段变化的情况,则日志表中只需要记录关键字段变化即可,但操作人,操作类型,时间应当准确记录,日志表数据一旦生成不允许进行修改。如用户账户的充值流水,消费流水都是一些业务紧相关的日志。而审核日志,操作记录等日志则属于与业务关联较小的日志。

3. 针对所有历史需要保留的数据则需要每次变化都生成一个新的版本,比如类目信息等,对原始数据永远只做insert操作,不做delete及update操作。但这种情况仅限于极端数据历史要求极高的情况下使用。


© 著作权归作者所有

董泽润
粉丝 2
博文 3
码字总数 4121
作品 0
海淀
私信 提问
MYSQL数据库命名及设计规范

1.设计原则 1) 标准化和规范化 数据的标准化有助于消除数据库中的数据冗余。标准化有好几种形式,但Third Normal Form(3NF)通常被认为在性能、扩展性和数据完整性方面达到了最好平衡。简单...

万里虎
2014/12/04
388
0
Yii2 Day 5: 创建用户模块

在确定了模块化开发应用的方向后,可以尝试写一个模块练练手啦。首先想到的就是用户模块。 前后台用户分离 通常一个应用会存在前台用户和后台用户,这两个用户的Session变量必须是分开的,不...

_Elvis
2014/12/17
6.5K
1
mysql web数据库的设计归范-1命名规范

[数据库环境介绍] 通常来讲,各个互联网公司的数据库分为5个数据库环境: 1. dev : 开发环境, 开发可读写,可修改表结构; 常用的163的数据库表; 开发人员可以修改表结构, 可以随意修改其中的数...

董泽润
2014/07/11
11.6K
0
MySQL 性能优化,优化设计及设计原则解读

MySQL性能优化的目的 如何合理的设计数据库? 什么样的数据库设计才能给后期DBA优化提供基石? 数据库设计与程序设计的差异? 数据库设计早期优化 1. 关系明确(理清表之间的关系,可以通过冗...

Java填坑之路
2018/08/22
0
0
PHPer面试指南-MySQL 篇

本书的 GitHub 地址:https://github.com/todayqq/PHPerInterviewGuide 什么是索引,作用是什么?常见索引类型有那些?Mysql 建立索引的原则? 索引是一种特殊的文件,它们包含着对数据表里所...

angkee
2018/01/24
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Leetcode PHP题解--D118 350. Intersection of Two Arrays II

D118 350. Intersection of Two Arrays II 题目链接 350. Intersection of Two Arrays II 题目分析 返回给定两个数组的交集。 思路 从数量较多的那个数组开始去另一个数组寻找是否元素存在,...

skys215
14分钟前
2
0
从源码上分析Android View保存数据状态

在Android开发旅途中,经常会遇到系统控件无法满足我们的视觉,交互效果,这个时候我们常常需要自己自定义控件来满足我们的需求。在这个开发探索过程中,我们不可避免得遇到View要保存状态信...

shzwork
15分钟前
2
0
请问AD603AQ和AD603AR有什么区别?

  AD603AQ和AD603AR只是在封装上的区别,前者是双列直插式,后者是贴片式,AD603A系列的温度都是在—40摄氏度到+85摄氏度之间,AD603还有一个系列是AD603S,它的温度是在—55摄氏度到+125摄...

仙溪
16分钟前
2
0
Linux /etc/profile 配置文件修改

1. 执行命令: vi /etc/profile 去类似windows 配置环境变量, 2.修改完,立即生效命令: source /etc/profile

kuchawyz
17分钟前
2
0
对于小白来说素描怎么入门?怎么学习?

素描初学者怎样入门?初学者怎样才能画好素描绘画?画好素描绘画有哪些技巧?想必这些问题都是绘画初学者们比较伤脑筋的问题,那么初学者到底怎样才能画好素描绘画呢?今天收集整理了关于素描...

huihuajiaocheng
18分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部