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技巧:一次删除一百万个文件的最快方法
最初的测评 昨天,我看到一个非常有趣的删除一个目录下的海量文件的方法.这个方法来自http://www.quora.com/How-can-someone-rapidly-delete-400-000 ...
- 使用Python做简单的字符串匹配
由于需要在半结构化的文本数据中提取一些特定格式的字段.数据辅助挖掘分析工作,以往都是使用Matlab工具进行结构化数据处理的建模,matlab擅长矩阵处理.结构化数据的计算,Python具有与matl ...
- Android开发技巧——ViewPager衍生出来的2个类
1.不能左右滑动的ViewPager /* * Date: 14-7-28 * Project: Access-Control-V2 */ package cn.irains.access.v2.co ...
- 怎么在Eclipse中添加VI插件
下载地址 Vi插件下载位置 怎么安装? 将下载下来的zip文件进行解压,然后把对于的目录下的文件分别复制到eclipse目录下的plugins 和features目录下: 注册 在eclipse根目录 ...
- Android 有关于* daemon not running.starting it now on port 5037 *ADB
adb shell时出现以下信息: * daemon not running. starting it now on port5037 * ADB server didn't ACK * fail ...
- 《java入门第一季》之Socket编程通信和TCP协议通信图解
Socket编程通信图解原理: TCP协议通信图解
- android 解析服务器数据使用json还是xml方式
整理自百度搜索: 现在的Android应用程序,几乎没有不与服务端交换数据的了!那么,android应用在与服务端交换数据的时候,我们有哪些选择呢?哪种数据交换格式要更好吗?下面文章简单为 andro ...
- 小试ImageMagik——开发篇
===================================================== ImageMagick的使用和开发的文章: 小试ImageMagik--使用篇 小试Imag ...
- 【一天一道LeetCode】#26. Remove Duplicates from Sorted Array
一天一道LeetCode系列 (一)题目 Given a sorted array, remove the duplicates in place such that each element app ...
- android 面试之listview
ListView优化一直是一个老生常谈的问题,不管是面试还是平常的开发中,ListView永远不会被忽略掉,那么这篇文章我们来看看如何最大化的优化ListView的性能.· 1.在adapter中的g ...