良好的数据库逻辑设计和物理设计是数据库高性能的基础,所以对于数据库结构优化是很有必要的

数据库结构优化目的:

1、减少数据的冗余

2、尽量避免在数据插入、删除和更新异常

例如:有一张设计不得当的学生选课表

CREATE TABLE selectcourse(
stu_no INT(11) NOT NULL COMMENT '学号',
stu_name VARCHAR(10) NOT NULL COMMENT '学生姓名',
birth_date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '生日',
course_name VARCHAR(10) NOT NULL COMMENT '课程名称',
score INT(11) DEFAULT NULL COMMENT '成绩',
course_point INT(11) NOT NULL COMMENT '学分',
PRIMARY KEY(stu_no, course_name)
) ENGINE = INNODB DEFAULT CHARSET=utf8

查询结果:

1	sam	1994-06-22 16:19:39	数学		10
1 sam 2019-06-22 16:21:02 英语 9
2 jesen 1995-06-22 16:19:39 数学 10
2 jesen 1995-06-22 16:22:27 英语 9

插入异常:

  如果表中某个实体依赖另一个实体而存在,想添加一门语文课,但是依赖学生、学号等

更新异常:

  更新表中某个实体的单独属性时,需要对多行进行更新,如果把数学的学分进行更新,就需要更新多条数据

删除异常:

  删除表中某个实体,导致其他实体也被删除,想要删除英文这门课,但是也会被选择语文课的学生信息也删除

3、解决数据库存储空间

4、提高查询效率

结构优化设计步骤:

1、需求分析:存储需求、数据处理需求、安全性要求等

2、逻辑设计:

  1、设计数据的逻辑存储结构

  2、数据实体之间的逻辑关系,解决数据冗余和数据存储异常

3、物理设计:

  根据使用的数据库特点设计表结构

4、维护优化:

  根据实际情况对索引、存储结构进行优化

数据库三范式:

第一范式:

  数据库表中字段都是单一属性,不能再进行细化分解

第二范式:

  表中只有一个业务主键,不能存在非主键列对主键存在部分依赖,如果主键是单一列肯定符合,但是如果是复合主键,就肯定可能

不满足这一要求。

  例如上面的selectcourse表,主键:PRIMARY KEY (`stu_no`,`course_name`),学分只是依赖课程列,学生姓名只是依赖学号,

所以为了满足第二范式要求,需要对表进行拆分

  拆分为:学生表、课程表、学生选课表

第三范式:

  每个非主属性不能对业务主键存在依赖传递,消除了第二范式基础上非主键列对主键的传递依赖

  例如,现在学生表里面存在着学院,学院电话等信息,学院电话通过学院与学生表产生传递依赖,我们需要再拆分成学员信息表

满足三范式,基本就解决了数据冗余和数据异常的问题,但是不是一定要满足,看实际需求的,有时候需要反范式设计

需求分析和逻辑设计实战:

设计出下面电商网站的数据库结构

需求:

1、只销售图书类商品

2、需要以下功能

  1).用户登录

  2).商品展示

  3).供应商管理

  4).用户管理

  5).商品管理

  6).在线销售

需求分析:

用户登录:

  1、用户必须注册并登录系统才能进行交易

  2、同一时间只能一个用户在一个地方登录

  3、用户信息:{用户名(主键),密码,手机号,姓名,注册信息,在线状态,生日}

商品展示和管理功能:

  商品信息:{商品名称,分类名称,出版社名称,图书价格,图书描述,作者}

  但是这样设计不符合三范式,如果增加一个分类,但是没有商品,是无法添加的,所以需要表拆分

  商品信息表:{商品名称,出版社名称,价格,描述,作者}

  分类信息表:{分类名称,分类描述}

  商品分类对应表:{商品名称、分类名称}

供应商管理:

  供应商信息:{出版社名称,地址,电话,联系人,银行账户}

在线销售:

  在线销售表:{订单编号,订单用户名,订单日期,订单金额,订单商品分类,订单商品名,订单商品单价,订单商品数量,支付金额,物流单号}

  1、只有一个业务主键,符合第二范式

  2、订单编号,订单商品数量,订单商品单价存在传递依赖关系,不符合第三范式

  3、数据冗余:订单商品信息和商品信息表的数据

  拆分:

  订单表:{订单编号,订单用户名,订单日期,支付金额,物流单号}

  订单商品关联表:{订单编号,订单商品分类,订单商品名,支付金额,商品数量}

现在查询一个用户订单总金额的SQL:

select 订单用户名,sum(d.商品价格*d.商品数量) from 订单表 a join 订单商品关联表 b on a.订单编号 = b.订单编号

    join 商品分类关联表 c on c.商品名称 = b.商品名称 and c.分类名称 = b.订单商品分类

    join 商品信息表 d on d.商品名称 = c.商品名称

group by 下单用户名

我们发现管理的表太多,会导致性能变得的很差

查询下单用户和订单详情:SQL也会关联的很复杂

总结:完全符合三范式,可能导致SQL查询性能变差,所以需要反范式化设计

反范式化:

  为了性能和效率的考虑适当的违反范式化设计要求,允许存在少量的数据冗余,就是以空间换时间

对商品信息进行反范式化设计:

  商品信息表:{商品名称,分类名称,出版社名称,价格,描述,作者}

  分类信息表:{分类名称,分类描述}

现在查询一个用户订单总金额的SQL:

  select 订单用户名,sum(订单金额) from 订单表 group by 下单用户名

  订单表:{订单编号,订单用户名,手机号,订单日期,支付金额,物流单号,订单金额}

  订单商品关联表:{订单编号,订单商品分类,订单商品名,商品单价,商品数量}

范式化设计和反范式化设计的对比:

  1、范式化可以尽量的减少数据冗余

  2、范式化的更新操作比反范式化更快

  3、范式化的表通常比反范式化的表要小

  4、反范式化减少表的关联

  5、反范式化相比范式化可以更好的对索引进行优化,例如使用覆盖索引

物理设计:

  1、定义数据库、表和字段的命名规范

  命名蹲守可读性原则、表意性原则、长名原则,注意MySQL是区分大小写的

  2、选择合适的存储引擎

  3、为表中的字段设计合适的数据类型

  参考我之前写过的一篇文章:MySQL系列(一)--数据类型

  4、建立数据库表结构

MySQL系列(三)--数据库结构优化的更多相关文章

  1. 《打造扛得住的MySQL数据库架构》第4章 MySQL数据库结构优化

    4-1 数据库结构优化介绍 良好的数据库逻辑设计和物理设计是数据库获得高性能的基础. 1.减少不必要的数据冗余. 2.尽量避免数据维护中出现更新,插入和删除异常. 插入异常:如果表中的某个实体随着另一 ...

  2. MYSQL 数据库结构优化

    数据库结构优化 优化数据大小 使表占用尽量少的磁盘空间.减少磁盘I/O次数及读取数据量是提升性能的基础原则.表越小,数据读写处理时则需要更少的内存,同时,小表的索引占用也相对小,索引处理也更加快速. ...

  3. mysql性能优化学习笔记(5)数据库结构优化

    一.选择合适的数据类型    1.使用可存下数据的最小的数据类型    2.使用简单地数据类型,Int<varchar    3.尽可能使用not null定义字段    4.尽量少用text, ...

  4. Mysql 性能优化5【重要】数据库结构优化

    数据库设计的步骤 我们大多使用mysql 设计三范式 设置时区  

  5. MySQL强人“锁”难《死磕MySQL系列 三》

    系列文章 一.原来一条select语句在MySQL是这样执行的<死磕MySQL系列 一> 二.一生挚友redo log.binlog<死磕MySQL系列 二> 前言 最近数据库 ...

  6. 性能优化系列三:JVM优化

    一.几个基本概念 GCRoots对象都有哪些 所有正在运行的线程的栈上的引用变量.所有的全局变量.所有ClassLoader... 1.System Class.2.JNI Local3.JNI Gl ...

  7. MySQL之数据库结构优化

    1.选择合适的数据类型 一.选择能够存下数据类型最小的数据类型 二.可以使用简单的数据类型.int  要比varchar在MySQL处理上简单 三.尽可能的使用not null  定义字段 四.尽量少 ...

  8. MySQL优化三 表结构优化

    由于MySQL数据库是基于行(Row)存储的数据库,而数据库操作 IO 的时候是以 page(block)的方式,也就是说,如果我们每条记录所占用的空间量减小,就会使每个page中可存放的数据行数增大 ...

  9. 【MySQL优化】数据库结构优化

    原则: 设计表结构,字段类型,最小化磁盘存储的空间,减少IO.数据库操作中最为耗时的操作就是 IO 处理,大部分数据库操作 90% 以上的时间都花在了 IO 读写上面.所以尽可能减少 IO 读写量,可 ...

随机推荐

  1. idea类名下有红色波浪线

    能编译通过说明SDK导入正确,但是为啥我们点击每一个Java文件会出现好多红色的下划线 ,并提示idea cant resolve symbol 原因就是可能没有清除原来的历史缓存,导致一些错误,解决 ...

  2. vue项目中的路径别名

    每次写引入组件的路径,如果路径嵌套比较深,那么会比较麻烦,我们可以在webpack.base.conf.js,中设置路径的别名,默认webpack设置src的别名为@ 建议配置src下一级目录的别名, ...

  3. centos7命令行模式安装&&配置_br0+kvm+虚拟机+添加硬盘+快照及恢复

    KVM创建虚拟机步骤 Submitted by zhaoley on October 18, 2016 - 10:43am 测试环境: 1: 43.243.130.89, CentOS Linux r ...

  4. linux软硬连接学习总结

    创建连接实质上就是给系统中已经存在的文件指定另外一个可以访问它的名称,linux系统当中连接的创建有两种形式:硬链接(Hard Link),与符号链接(Symbloic Link)既软链接. ln命令 ...

  5. HDU 5879 Cure (数论)

    题意:给定n,求前 n 项 1/(k*k) 的和. 析:由于这个极限是 PI * PI / 6,所以我们可以找到分界点,然后计算就好. 代码如下: #pragma comment(linker, &q ...

  6. django url 规则正确,却一直匹配错误,django url匹配错误的可能原因

    首先看一下我想要匹配的规则如下 这个url之前设计的是 joke/index/ 后来需要加page参数就把'/'去掉了 然后再用 joke/index去访问页面时总显示 当我把鼠标放到对应连接时,显示 ...

  7. web服务端的架构演变

    此文已由作者肖凡授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 最近Lofter项目碰到很多性能上的问题,特别是数据库相关的,每次推送后,告警就会第一时间到来.这些问题随着产 ...

  8. PTA 朋友圈【并查集的合并问题】

    一开始,考虑的是每次就是把第一个作为祖先,这样很明显是错误的,比如 7 4 3 1 2 3 2 4 2 3 5 6 7 1 6 所以这正是更好地体现对于集合的代表.只有把所有的元素合并一下,然后选一个 ...

  9. Luogu P1607 庙会班车【线段树】By cellur925

    题目传送门 据说可以用贪心做?算了算了...我都不会贪.... 开始想的是用线段树,先建出一颗空树,然后输进区间操作后就维护最大值,显然开始我忽视了班车的容量以及可以有多组奶牛坐在一起的信息. 我们肯 ...

  10. jQuery 第九章 工具方法

    $.type() $.isArray() $.isFunction() $.isWindow()... $.trim() $.proxy() $.noConflict() $.each() $.map ...