Mysql数据库表结构设计

3,493 阅读15分钟
1.数据库结构设计的步骤


数据库的设计步骤是随着产品需求的不断变更而循环往复的


首先对产品的需求进行分析,全面了解产品设计的存储需求,形成需求分析文档,这一步是非常重要的,决定了是否可以设计出符合实际需求的、高效的数据库模型,很多存在性能问题的数据库都是由于一开始没有做好需求分析造成的,可以想象一下,如果我们的需求分析做的不全面就一定会造成产品上线后,频繁的修改数据库结构这样的问题,造成原本设计的高效的数据库结构在多次修改后就变得难以使用了,严重的情况下还会造成数据冗余和写维护异常这样的问题;需要分析这块主要做的主要工作是要全面了解产品设计对数据库的存储需求,调查、收集和分析所要开发的产品在数据库中 数据存储需求、以及数据处理需求、数据的安全性和完整性都是什么;


数据存储需求:数据库需要存储什么样的数据,这些数据具有什么样的特点


数据处理需求:如何对数据库数据进行读取、修改以及完成产品设计的功能、以及对数据处理的响应时间有什么样的要求,数据处理的方式时批量处理呢还是连接处理


其次就是对逻辑设计阶段,在这个阶段我们不用关心使用的是什么数据库或者说是什么存储引擎,这个阶段主要是搞清楚,数据实体之间的逻辑关系,要解决数据冗余和数据维护异常重点就在这个阶段,这个阶段主要做的工作不但重要而且还直接影响以后的数据处理和数据存储方式;想要设计出符合需求的、解决数据冗余的和数据维护异常且高效的数据库逻辑设计是不容易的,不过好在这个阶段有一些设计秘籍可以参考,这些秘籍就是数据库的设计范式,设计范式主要按照要求进行数据库的设计,可以最大程度的解决数据冗余和维护异常这样的问题;


然后再进行数据库的物理设计阶段,根据所使用的数据库特点进行表结构设计和建立,常用的关系型数据库:Oralce、SQLServer、Mysql,postgresSQL


非关系型数据库:mongo,redis,Hadoop


最后就是对数据库进行维护和优化,根据实际情况对索引、存储结构等进行优化



2.数据库设计范式


在进行数据库的设计时,所遵循的一些规范,只要按照设计规范进行设计,就能设计出没有数据冗余和数据维护异常的数据库结构


数据库的设计的规范有很多,通常来说我们在设计数据库时只要达到其中一些规范就可以了,这些规范又称之为数据库的三范式,一共有三条,也存在着其他的范式,我们只要做到满足前三个范式的要求,就能设计出符合我们的数据库了,我们也不能全部来按照范式的要求来做,还要考虑实际的业务使用情况,所以有时候也需要做一些违反范式的要求


数据库设计的第一范式(最基本),基本上所有数据库的范式都是符合第一范式的,符合第一范式的表具有以下几个特点:


数据库表中的所有字段都只具有单一属性


单一属性的列是由基本的数据类型(整型,浮点型,字符型等)所构成的


设计出来的表都是简单的二维表


数据库设计的第二范式(是在第一范式的基础上设计的),要求一个表中只具有一个业务主键,也就是说符合第二范式的表中不能存在非主键列对只对部分主键的依赖关系


数据库设计的第三范式,指每一个非主属性既不部分依赖于也不传递依赖于业务主键,也就是在第二范式的基础上消除了非主属性对主键的传递依赖


什么叫做反范式化设计


反范式化是针对范式化而言的,在前面介绍了数据库设计的范式,所谓的反范式化就是为了性能和读取效率的考虑而适当的对数据库设计范式的要求进行违反,而允许存在少量的数据冗余,换句话来说反范式化就是使用空间来换取时间


范式化设计和反范式化设计优缺点


范式化的优点:


1.可以尽量的减少数据冗余,数据表更新快体积小


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


3.范式化的表通常比反范式化更小


范式化的缺点:


1.对于查询需要对多个表进行关联


2.更难进行索引优化;例如,范式化会将经常使用到的列存放在不同的表中,而这些列在同一个表中的话,本来是可以使用同一个索引的,而在不同的表中,我们就无法放到同一个索引中了


反范式化的优点:


1.反范式化经常在一张表中查询,这样可以很好的减少表的关联操作,而对于不需要关联的表,大多数情况下最差的性能也就是会进行全表扫描,就算是数据比内存大的很多,无法在表中缓存数据



3.物理设计结构介绍


概念:根据所选择的关系型数据库的特点对逻辑模型进行存储结构设计


mysql在物理结构的设计包括以下内容


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


我们当前的程序项目开发往往是多个人协作来完成,所以为了工作中的沟通方便,我们就需要为数据库、表及字段起名字遵守一个共同的约定和规范,这就是命名规范,符合我们的这种命名规范来建立数据库和表结构应该是能够使大家呢,在不用查看数据库字典的情况下,就能基本的知道这个库表中以及表中的字段的大概内容是什么;为了做到这一点,我们在为数据库命名时,应该做到以下几点:


1.数据库、表及字段的命名要遵守可读性原则 (所谓的可读性原则就是在数据库对象命名时,我们应该尽量的使名称有更好的可读性,比如使用下划线来分割不同的单词或者对某个单词的首字母进行大写等等,要注意的是,对mysql来说对表名的大小写是敏感的,如果我们使用大小写字母的方式来 区分,这种命名不同的部分,会在以后在以后使用中造成不必要的麻烦)


2.数据库、表及字段的命名要遵守表意性原则(也就是在对象命名时,起的表名可以直接明白表的内容)


3.数据库、表及字段的命名要遵守长名原则 (有些开发人员在进行命名时,喜欢比较短的名字,这种名字无法体现出表的内容,尽量少的使用缩写,也不能太长,否则使用起来不太方便)


以上原则还是要遵守一个适度的原则


2.为表中的字段选择合适的数据类型


为表中的字段选择合适的数据类型其实是一个技术活,发现大多数的开发人员为选择合适的表的字段不是太重视,对于字符串类型往往选择255这样的默认值,字段类型的选择对数据库的性能有着很大的影响,而过大的数据类型往往会浪费足够的内存和磁盘IO,这两种资源在数据库中都是十分珍贵的,以下是字段类型选择的一个原则:当一个列可以选择多种数据类型时,应该优先考虑数字类型,其次是日期或二进制类型,最后是字符串类型;对于相同级别的数据类型,应该优先选择占用空间小的数据类型,之所以这样说,主要是由于以下几个原因:首先对数据进行比较,比如说查询条件、聚合条件关联排序时,字符类型处理与当前所使用的排序的规则是相关的,数字与二进制不需要参考字典的排序规则,其处理是按照二进制大小来进行的,同样的数据,字符串处理往往比数字处理要慢,另外在数据库中,数据处理是以页为单位的,每一页能存储的数据量是一定的,在Innodb中是16k,页的长度越小,意味着在页中能容乃的数据行数越多,这样在加载同样的数据时,使用宽度较小的类型比使用宽度较大的类型所要加载的数据页少,从而减少了磁盘的IO,有利于性能的提升,这个原则看上去很简单,真的要做好是不容易的,下面针对各种数据类型的使用的方法来给大家分析一下


1.如何选择正确的整数类型

2.如何选择正确的实数类型

3.如何选择VARCHAR和CHAR类型


这两种于磁盘的存储方式有很大的关系,下面用Innodb的存储类型做为讲解


1.varchar类型的存储特点
1.varchar用于存储变长字符串的,只占用必要的存储空间,varchar和char中定义的宽度是以字符为单位的,而不是以字节的;以utf-8字符集为例,在varchar中存储10个字符,就需要varchar的宽度为30,而实际上只需要在Varchar定义10个就可以了,这也是经常不能正确定义varchar的一个主要原因 ;


2.每一个varchar列的最大长度小于255则只会占用一个额外字节用于记录变长字符串长度,而当一个varchar列的最大长度大于255则占用两个额外字节用于记录字符串长度,这就决定了varchar的最大宽度是65535字节,但是在实际中不可能为varchar列建立这么大的长度,对于innodb来说,65535个字节是一行中所有的varchar列共享的一个长度,如果定义一个非常的大varchar数据类型的长度就需要使用text这种类型来存储;varchar长度的选择问题也对数据库的性能有着重要的影响,在决定varchar长度的问题上有一个总的原则,就是使用最小的符合需求的长度,这个原则看起来很简单,做到的话是非常不简单的,我们很难确定什么是最小的符合需求的长度,为了解决这个问题,我们必须得对业务非常的了解,只有真正的了解了业务和所需要存储的数据,才知道什么样的长度是一个合理的范围,比如说用户姓名这一列,如果我们主要存储的只是中文名的话,这一列不会超过10个字符,很少有中文名字是10个字的,如果还要存储外国人的名字的话,我们需要存储的就需要20个字符了,外国人的名字通常是很长的,但是无论如何也不应该使用varchar(255)这样的宽度来定义,因为我相信不会有人起255个字这样的名字;另外还有一个点需要注意,我们希望varchar列的长度尽可能的小,但是也并不说不管业务的实际情况只顾把varchar列的宽度设置的很小,想要以后如果这个长度不够了我们再修改为更大的长度,其实这个想法是十分不正确的,因为一旦业务上线,列的长度修改的成本是十分大的,在mysql5.7之前的版本中,对varchar列的宽度不论是改大还是改小都是要锁表的,就像在mysql5.7和5.7之后也只是说,如果varchar列原来的宽度是255个字节以内,如果改变后的宽度同样不超过255个字符就可以不锁表了;一旦在生产环境中发生了锁表的问题,在一个繁忙的系统中,一定会出现一个影响性能问题的;


varchar的适用场景

1.字符串列的最大长度比平均长度大很多,因为这样才能凸显出varchar变长存储的特点


2.适合存储很少被更新的字符串,因为varchar类型更新由于字符串的长度会产生变化,可能引起存储页的分裂,造成很多的存储碎片;


3.适合存储使用多字节字符集存储字符串,因为可能有不同字节数进行存储,utf8存储需要3个字节,存储英文或者数字只需要一个字节


2.char类型的存储特点:


1.char类型是定长的,mysql根据定义char类型的宽度,来分配足够的空间来存储char类型的数据


2.字符串存储在char类型的列中会删除末尾的空格,如果在varchar类型中末尾有空格就不会被删除


3.char类型的最大宽度为255,如果超过255就要选择varchar类型,这就是varchar在存储上的一些特点


char类型适用的场景


1.char类型适合存储所长度的近似的值


2.char类型适合存储短字符串


3.char类型适合存储经常更新的字符串列


4.如何存储日期数据


1.DATATIME类型:以YYYY-MM-DD HH:MM:SS[.fraction] 格式存储日期时间


datatime = YYYY-MM-DD HH:MM:SS


在mysql5.6之前能存储时间的最小精度为秒,而在mysql5.6之后,我们可以利用datatime类型存储包括微秒的日期时间值,但是在默认情况下还保存秒的时间值,如果想保存到微秒就需要为日期时间类型定义一个宽度,这个宽度的最大值为6;如果我们想保存6位微秒时间值,就需要 datatime(6) = YYYY-MM-DD HH:MM:SS.fraction,datatime类型与时间无关的,也就是存在datatime的日期是不会根据时区的变化而变化的,如果在多个不同时区使用相同的数据,就需要特别的注意 ;占用8个字符的存储空间;时间范围:1000-01-01 00:00:00到9999-12-31 23:59:59 一般情况下都使用datatime来存储时间


2.TIMESTAMP类型:存储了由格林尼治时间1970年1月1日到当前时间的秒数; 以YYYY-MM-DD HH:MM:SS.[.fraction] 的格式显示占用4个字节,也可以给TIMESTAMP类型指定一个宽度用来存储微秒数据,相比于datatime类型来时间戳只占用4个字节,实际上是用int来存储的 ,TIMESTAMP类型所存储的时间范围要比datatime类型要小的多,由于存储空间的限制,时间戳类型存储的时间范围1970-01-01 到 2038-01-19;显示上和datatime类型是一样的,它比datatime要节约空间


timestamp类型显示依赖于所指定的时区,我们存储的时间值在不同的时区可能显示不同的值,如果在多个时区的环境下来使用这个数据的话,datatime和timestamp的处理是有区别的;最后timestamp类型还有一个最大的特点,在一个表中指定一个timestamp列,在本行的任何数据被修改时都会自动修改timestamp列的值,这个功能非常有用,我们经常使用这个功能来标识每行数据的最后修改时间,这样呢,我们的数据分析类应用就可以按照这个列来增量的处理数据库中的数据

更多免费技术资料可关注:annalin1203