6.4 Schema 设计对系统的性能影响
前面两节中,我们已经分析了在一个数据库应用系统的软环境中应用系统的架构实现和系统中与数
据库交互的SQL 语句对系统性能的影响。在这一节我们再分析一下系统的数据模型设计实现对系统的性
能影响,更通俗一点就是数据库的Schema 设计对系统性能的影响。
在很多人看来,数据库Schema 设计是一件非常简单的事情,就大体按照系统设计时候的相关实体对
象对应成一个一个的表格基本上就可以了。然后为了在功能上做到尽可能容易扩展,再根据数据库范式
规则进行调整,做到第三范式或者第四范式,基本就算完事了
数据库Schema 设计真的有如上面所说的这么简单么?可以非常肯定的告诉大家,数据库Schema 设计
所需要做的事情远远不止如此。如果您之前的数据库Schema 设计一直都是这么做的,那么在该设计应用
于正式环境之后,很可能带来非常大的性能代价。
由于在后面的“MySQL 数据库应用系统设计”中的“系统架构最优化“这一节中会介较为详细的从
性能优化的角度来分析如何如何设计数据库Schema,所以这里暂时先不介绍如何来设计性能优异的数据
库Schema 结构,仅仅通过一个实际的示例来展示Schema 结构的不一样在性能方面所带来的差异。
需求概述:一个简单的讨论区系统,需要有用户,用户组,组讨论区这三部分基本功能
简要分析:1、需要存放用户数据的表;
2、需要存放分组信息和存放用户与组关系的表
3、需要存放讨论信息的表;
解决方案:
原始方案一:分别用用四个表来存放用户,分组,用户与组关系以及各组的讨论帖子的信息如
下:
user 用户表:
+-------------+---------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+---------------+------+-----+---------+-------+
| id | int(11) | NO | | 0 | |
| nick_name | varchar(32) | NO | | NULL | |
| password | char(64) | YES | | NULL | |
| email | varchar(32) | NO | | NULL | |
| status | varchar(16) | NO | | NULL | |
| sexuality | char(1) | NO | | NULL | |
| msn | varchar(32) | YES | | NULL | |
| sign | varchar(64) | YES | | NULL | |
| birthday | date | YES | | NULL | |
| hobby | varchar(64) | YES | | NULL | |
| location | varchar(64) | YES | | NULL | |
| description | varchar(1024) | YES | | NULL | |
+-------------+---------------+------+-----+---------+-------+
groups 分组表:
+--------------+---------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+---------------+------+-----+---------+-------+
| id | int(11) | NO | | NULL | |
| gmt_create | datetime | NO | | NULL | |
| gmt_modified | datetime | NO | | NULL | |
| name | varchar(32) | NO | | NULL | |
| status | varchar(16) | NO | | NULL | |
| description | varchar(1024) | YES | | NULL | |
+--------------+---------------+------+-----+---------+-------+
user_group 关系表:
+--------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+-------+
| user_id | int(11) | NO | MUL | NULL | |
| group_id | int(11) | NO | MUL | NULL | |
| user_type | int(11) | NO | | NULL | |
| gmt_create | datetime | NO | | NULL | |
| gmt_modified | datetime | NO | | NULL | |
| status | varchar(16) | NO | | NULL | |
+--------------+-------------+------+-----+---------+-------+
group_message 讨论组帖子表:
+--------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+-------+
| id | int(11) | NO | | NULL | |
| gmt_create | datetime | NO | | NULL | |
| gmt_modified | datetime | NO | | NULL | |
| group_id | int(11) | NO | | NULL | |
| user_id | int(11) | NO | | NULL | |
| subject | varchar(128) | NO | | NULL | |
| content | text | YES | | NULL | |
+--------------+--------------+------+-----+---------+-------+
优化后方案二:
user 用户表:
+-------------+---------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+---------------+------+-----+---------+-------+
| id | int(11) | NO | | 0 | |
| nick_name | varchar(32) | NO | | NULL | |
| password | char(64) | YES | | NULL | |
| email | varchar(32) | NO | | NULL | |
| status | varchar(16) | NO | | NULL | |
+-------------+---------------+------+-----+---------+-------+
user_profile 用户属性表(记录与user 一一对应):
+-------------+---------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+---------------+------+-----+---------+-------+
| sexuality | char(1) | NO | | NULL | |
| msn | varchar(32) | YES | | NULL | |
| sign | varchar(64) | YES | | NULL | |
| birthday | date | YES | | NULL | |
| hobby | varchar(64) | YES | | NULL | |
| location | varchar(64) | YES | | NULL | |
| description | varchar(1024) | YES | | NULL | |
+-------------+---------------+------+-----+---------+-------+
groups 和user_group 这两个表和方案一完全一样
group_message 讨论组帖子表:
+--------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+-------+
| id | int(11) | NO | | NULL | |
| gmt_create | datetime | NO | | NULL | |
| gmt_modified | datetime | NO | | NULL | |
| group_id | int(11) | NO | | NULL | |
| user_id | int(11) | NO | | NULL | |
| author | varchar(32) | NO | | NULL | |
| subject | varchar(128) | NO | | NULL | |
+--------------+--------------+------+-----+---------+-------+
group_message_content 帖子内容表(记录与group_message 一一对应):
+--------------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+---------+------+-----+---------+-------+
| group_msg_id | int(11) | NO | | NULL | |
| content | text | NO | | NULL | |
+--------------+---------+------+-----+---------+-------+
我们先来比较一下两个解决方案所设计的Schema 的区别。区别主要体现在两点,一个区别是在
group_message 表中增加了author 字段来存放发帖作者的昵称,与user 表的nick_name 相对应,另外一
个就是第二个解决方案将user 表和group_message 表都分拆成了两个表,关系分别都是一一对应。
方案二看上去比方案一要更复杂一些,首先是表的数量多了2 个,然后是在group_message 中冗余存
放了作者昵称。我们试想一下,一个讨论区系统,访问最多的页面会是什么?我想大家都会很清楚是帖
子标题列表页面。而帖子标题列表页面最主要的信息就是都是来自group_message 表中,同时帖子标题
后面的作者一般都是通过用户名成(昵称)来展示。按照第一种解决方案来设计的Schema,我们就需要
执行类似如下这样的SQL 语句来得到数据:
SELECT t.id, t.subject,user.id, u.nick_name
FROM (
SELECT id, user_id, subject
FROM group_message
WHERE group_id = ?
ORDER BY gmt_modified DESC LIMIT 20
) t, user u
WHERE t.user_id = u.id
但是第二中解决方案所需要执行的SQL 就会简单很多,如下:
SELECT t.id, t.subject, t.user_id, t.author
FROM group_message
WHERE group_id = ?
ORDER BY gmt_modified DESC LIMIT 20
两个SQL 相比较,大家都能很明显的看出谁优谁劣了,第一个是需要读取两个表的数据进行Join,
与第二个SQL 相比性能差距很大,尤其是如果第一个再写的差一点,性能更是非常糟糕,两者所带来的
资源消耗就更相差玄虚了。
不仅仅如此,由于第一个方案中的group_message 表中还包含一个大字段“content”,该字段所存
放的信息要占整个表的绝大部分存储空间,但在这条系统中执行最频繁的SQL 之一中是完全不需要该字
段所存放信息的,但是由于这个SQL 又没办法做到不访问group_message 表的数据,所以第一条SQL 在数
据读取过程中会需要读取大量没有任何意义的数据。
在系统中用户数据的读取也是比较频繁的,但是大多数地方所需要的用户数据都只是用户的几个基
本属性,如用户的id,昵称,密码,状态,邮箱等,所以将用户表的这几个属性单独分离出来后,也会
让大量的SQL 语句在运行的时候减少数据的检索量,从而提高性能。
可能有人会觉得,在我们将一个表分成两个表的时候,我们如果要访问被分拆出去的信息的时候,
性能不是就会变差了吗?是的,对于那些需要访问如user 的sign,msn 等原来只需要一个表就可以完成
的SQL 来说,现在都需要两条SQL 来完成,性能确实会有所降低,但是由于两个表都是一对一的关联关
系,关联字段的过滤性也非常高,而且这样的查询需求在整个系统中所占有的比例也并不高,所以这里
所带来的性能损失实际上要远远小于在其他SQL 上所节省出来的资源,所以完全不必为此担心
6.4 Schema 设计对系统的性能影响的更多相关文章
- 第 9 章 MySQL数据库Schema设计的性能优化
前言: 很多人都认为性能是在通过编写代码(程序代码或者是数据库代码)的过程中优化出来的,其实这是一个非常大的误区.真正影响性能最大的部分是在设计中就已经产生了的,后期的优化很多时候所能够带来的改善都只 ...
- MySQL性能调优与架构设计——第9章 MySQL数据库Schema设计的性能优化
第9章 MySQL数据库Schema设计的性能优化 前言: 很多人都认为性能是在通过编写代码(程序代码或者是数据库代码)的过程中优化出来的,其实这是一个非常大的误区.真正影响性能最大的部分是在设计中就 ...
- MySql(九):MySQL性能调优——Schema设计的性能优化
一.高效的模型设计 先了解下数据库设计的三大范式 第一范式:要求有主键,并且要求每一个字段原子性不可再分 第二范式:要求所有非主键字段完全依赖主键,不能产生部分依赖 第三范式:所有非主键字段和主键字段 ...
- MySQL性能调优与架构设计——第10章 MySQL数据库Schema设计的性能优化
第10章 MySQL Server性能优化 前言: 本章主要通过针对MySQL Server(mysqld)相关实现机制的分析,得到一些相应的优化建议.主要涉及MySQL的安装以及相关参数设置的优化, ...
- 数据库schema设计与优化
原文地址 1. 前言 对于数据库而言,在日常开发中我们主要的关注点有两块,一个是schema的结构设计,另一个就是索引的优化,这两块是影响我们最终系统结构和性能的关键部分,自然也是我们花费精力最多的部 ...
- Solr:Schema设计
本文已挪至 http://www.zhoujingen.cn/blog/8546.html Solr将数据以结构化的方式存入系统中,存储的过程中可以对数据建立索引,这个结构的定义就是通过schema ...
- 树形结构的数据库表Schema设计-基于左右值编码
树形结构的数据库表Schema设计 程序设计过程中,我们常常用树形结构来表征某些数据的关联关系,如企业上下级部门.栏目结构.商品分类等等,通常而言,这些树状结构需要借助于数据库完 成持久化.然而目前的 ...
- BizTalk开发系列(十二) Schema设计之Group与Order
开发BizTalk项目的时候会先约定各系统之间往来的消息格式. 由于BizTalk内部唯一使用XML文档.因此消息的格式为XML Schema(XML Schema 用于描述 XML 文档的结构).虽 ...
- 【转载】Linux系统与性能监控
原文地址:http://kerrigan.sinaapp.com/post-7.html Linux System and Performance Monitoring http://www.hous ...
随机推荐
- 初探linux子系统集之i2c子系统(二)
大概也是前年了,一直没有把那个i2c的子系统讲解完,这里偷个懒,把以前整理的i2c相关的知识再梳理一下,做个了结,然后再去学习timer子系统. 先看下i2c在内核中的代码分布: obj-$(CONF ...
- 使用TT模板+mvc+wcf实现简单查询
今天是除夕,小编的这篇博客是掐着点儿发的,在此,祝各位小伙伴新年快乐,身体健康,万事如意:喜从天降,欣喜若狂:喜气盈门,好事成双:好人好运,金玉满堂:神采飞扬,如愿以偿,财源滚滚来,福如东海长:伴随着 ...
- Cocos2D iOS之旅:如何写一个敲地鼠游戏(八):为动画建立属性列表
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交流 ...
- iOS动画进阶 - 教你写 Slack 的 Loading 动画
(转载自:http://blog.csdn.net/wang631106979/article/details/52473985) 如果移动端访问不佳,可以访问我的个人博客 前几天看了一篇关于动画的博 ...
- 输入过滤器——InputFilter
一般情况下我们通过请求体读取器InputStreamInputBuffer获取的仅仅是源数据,即未经过任何处理发送方发来的字节.但有些时候在这个读取的过程中希望做一些额外的处理,并且这些额外处理可能是 ...
- Java-IO之FileReader和FileWriter
FileReader是用于读取字符流的类,它继承于InputStreamReader,要读取原始字节流,考虑使用FileInputStream:FileWriter是用于写入字符流的类,继承于Outp ...
- Android初级教程理论知识(第一章快速入门)
一.综合介绍. Android项目的目录结构 Activity:应用被打开时显示的界面 src:项目代码 R.java:项目中所有资源文件的资源id Android.jar:Android的jar包, ...
- 5个你不知道的HTML5的接口
原文地址:5 HTML5 APIs You Didn't Know Existed 原文日期: 2010年09月27日 翻译日期: 2013年8月7日 当人们看到或者说出"HTML5&quo ...
- pig 的chararry类型不能用比较运算符comparison operator
pig 的chararry类型可能是按字段,逐个字段进行比较. element_id 是chararray类型, 语句: no_app_category_mapping = filter no_ele ...
- win7 VMware CentOS桥接(bridge)模式网络配置
主要内容参考自: centos下vmware 桥接设置静态ip例子 关于虚拟机网络配置的文章: Win7+VMware Workstation环境下的CentOS-Linux网络连接设置(推荐阅读) ...