前面两节中,我们已经分析了在一个数据库应用系统的软环境中应用系统的架构实现和系统中与数
据库交互的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 设计对系统的性能影响的更多相关文章

  1. 第 9 章 MySQL数据库Schema设计的性能优化

    前言: 很多人都认为性能是在通过编写代码(程序代码或者是数据库代码)的过程中优化出来的,其实这是一个非常大的误区.真正影响性能最大的部分是在设计中就已经产生了的,后期的优化很多时候所能够带来的改善都只 ...

  2. MySQL性能调优与架构设计——第9章 MySQL数据库Schema设计的性能优化

    第9章 MySQL数据库Schema设计的性能优化 前言: 很多人都认为性能是在通过编写代码(程序代码或者是数据库代码)的过程中优化出来的,其实这是一个非常大的误区.真正影响性能最大的部分是在设计中就 ...

  3. MySql(九):MySQL性能调优——Schema设计的性能优化

    一.高效的模型设计 先了解下数据库设计的三大范式 第一范式:要求有主键,并且要求每一个字段原子性不可再分 第二范式:要求所有非主键字段完全依赖主键,不能产生部分依赖 第三范式:所有非主键字段和主键字段 ...

  4. MySQL性能调优与架构设计——第10章 MySQL数据库Schema设计的性能优化

    第10章 MySQL Server性能优化 前言: 本章主要通过针对MySQL Server(mysqld)相关实现机制的分析,得到一些相应的优化建议.主要涉及MySQL的安装以及相关参数设置的优化, ...

  5. 数据库schema设计与优化

    原文地址 1. 前言 对于数据库而言,在日常开发中我们主要的关注点有两块,一个是schema的结构设计,另一个就是索引的优化,这两块是影响我们最终系统结构和性能的关键部分,自然也是我们花费精力最多的部 ...

  6. Solr:Schema设计

    本文已挪至  http://www.zhoujingen.cn/blog/8546.html Solr将数据以结构化的方式存入系统中,存储的过程中可以对数据建立索引,这个结构的定义就是通过schema ...

  7. 树形结构的数据库表Schema设计-基于左右值编码

    树形结构的数据库表Schema设计 程序设计过程中,我们常常用树形结构来表征某些数据的关联关系,如企业上下级部门.栏目结构.商品分类等等,通常而言,这些树状结构需要借助于数据库完 成持久化.然而目前的 ...

  8. BizTalk开发系列(十二) Schema设计之Group与Order

    开发BizTalk项目的时候会先约定各系统之间往来的消息格式. 由于BizTalk内部唯一使用XML文档.因此消息的格式为XML Schema(XML Schema 用于描述 XML 文档的结构).虽 ...

  9. 【转载】Linux系统与性能监控

    原文地址:http://kerrigan.sinaapp.com/post-7.html Linux System and Performance Monitoring http://www.hous ...

随机推荐

  1. Cocos2D iOS之旅:如何写一个敲地鼠游戏(十):创建游戏逻辑

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交流 ...

  2. SDL2源代码分析8:视频显示总结

    ===================================================== SDL源代码分析系列文章列表: SDL2源代码分析1:初始化(SDL_Init()) SDL ...

  3. iOS中 扫描二维码/生成二维码详解 韩俊强的博客

    最近大家总是问我有没有关于二维码的demo,为了满足大家的需求,特此研究了一番,希望能帮到大家! 每日更新关注:http://weibo.com/hanjunqiang  新浪微博 指示根视图: se ...

  4. SWING中文件的上传

    <pre name="code" class="java">import java.io.File; import java.io.FileInpu ...

  5. 01_Weblogic课程之概念篇:代理服务器,web服务器,应用程序服务器,JNDI概念,JTA概念,Java消息服务,Java验证和授权(JAAS),Java管理扩展,Web客户机,客户机应用程序

     1 什么是服务器 Weblogic中服务器分为两种,一种是受管服务器,另外一种是管理服务器. Weblogic课程(Weblogic是Oracle公司的,最开始的是BEA公司的) 一 系统管理 ...

  6. SQL Server扫盲系列——安全性专题——SQL Server 2012 Security Cookbook

    由于工作需要,最近研究这本书:<Microsoft SQL Server 2012 Security Cookbook>,为了总结及分享给有需要的人,所以把译文公布.预计每周最少3篇.如有 ...

  7. Linux信号实践(2) --信号分类

    信号分类 不可靠信号 Linux信号机制基本上是从UNIX系统中继承过来的.早期UNIX系统中的信号机制比较简单和原始,后来在实践中暴露出一些问题,它的主要问题是: 1.进程每次处理信号后,就将对信号 ...

  8. Optimizing Item Import Performance in Oracle Product Hub/Inventory

    APPLIES TO: Oracle Product Hub - Version 12.1.1 to 12.1.1 [Release 12.1] Oracle Inventory Management ...

  9. (NO.00001)iOS游戏SpeedBoy Lite成形记(六)

    为了能让玩家可以在比赛结束时清楚看到每位选手的成绩,我们需要在GameScene场景的track对象中添加一些新的元素. 在SpriteBuilder中打开GameScene.ccb,创建1个标签对象 ...

  10. mpi中程序在集群中的分发

    我们在开发mpi程序时,由于其是分布式程序,我们在单个节点上完成编码后,需要将代码拷贝到整个集群进行测试.集群之间的文件拷贝可以通过scp命令完成.但是scp命令是针对两个节点之间文件互传设计,为了将 ...