mysql物理设计

定义数据库,及表的命名规范:前端

1,数据库,表及字段的命名要遵循可读性原则, 表意性原则, 长名原则(不尽可能或者不使用缩写,使用长一些的命名,这样之后会看起来更明白,可是也不太很是的长)java

通一 主键的名称,好比是 id或者是 _id 等,这样比较好管理。表里面的字段命名也不须要带上表名什么的。什么意思就是什么意思就好,不必搞得这样子。不过表命名能够 但是 模块的名称 做为前缀 ,好比有一个 模块 crm ,那么 crm 模块里面 用到的表是 user ,那么表名 就起为  crm_user这样比较好识别和 管理。程序员

我的认为尽可能不要使用 uuid 的bigint ,通常的小中型项目,int无符号均可以知足了。算法

 

对于分布式的主键呢。数据库

通常都是使用 varchar 的 UUID,这样比较方便管理和使用对于分布式来讲。编程

可是对于一些对接其余系统的场景,ID可能会让你痛不欲生,而洗数据也是体力活儿。若是ID过长极容易产生前端显示问题,毕竟js的long是15位的。因此实际运用中ID长度也要严格把控。因此UUID 才保存为varchar类型,而不是 bigint 这样比较方便写代码和传给客户端,不用进行 类型转换了。服务器

 


 

文/codertom(简书做者)
原文连接:http://www.jianshu.com/p/a3828b42fce8
著做权归做者全部,转载请联系做者得到受权,并标注“简书做者”。网络

 

2, 为表中的字段选择合适的数据类型: 原则:数据库设计

当一个列能够选择多种数据类型时,应该优先考虑数字类型,其次是日期或二进制类型,最后的字符类型(char 类型 好比 varcahr类型好)分布式

对于相同级别的数据类型,应该优先选择占用空间小的数字类型

 

如何选择正确的整数类型?

tinyint  一个字节(无符号是取值范围 0--255), smallint 两个字节 , mediumint  三个字节

int 四个字节, bigint 八个字节 

 

如何选择正确的实数类型?

float  四个字节(不是精确类型) , double 八个字节(不是精确类型),decimal (每四个字节存9个数字,小数点占一个字节) (精确类型,但是占用的字节数也会多一些,若是是财务,钱的数据就应该使用这个类型,其余类型的数据,就能够用 float类型或者是  double类型了)。

 

如何选择 varchar 和 char 类型 ?

varchar 用于存储变长的字符串,只占用必要的存储空间(也就是内容是多少,就占用多少的空间),

列的最大长度小于255 (字符串长度),则只占用一个额外字节用于记录字符串长度。

若是列的最大长度大于255,则只占用两个额外的字节用于记录字符串长度。若是 字符串长度比较长,就应该使用 text 等其余的 类型进行存储 。

varchar 长度的选择问题: 使用最小的符合需求的长度。

若是项目上线后,多人使用的状况下,若是修改了 varchar 的长度 那么是会 进行锁表,那么会产生比较大的系统性能问题的,致使项目崩掉或者是其余数据问题,最好不要这么作。

使用 varchar的场景:

1, 字符串列的最大长度比平均长度大不少

2, 字符串列不多被更新

3,使用了 多字节字符集存储字符串

 

char 类型:

char类型 是定长的, 字符串存储在 char 类型中的列会删除末尾的空格,

char类型的 最大宽度是 255个类型 。

char类型 适用的 场景:

1,适合存储 所长度近似的值 (好比手机号,身份证等)

2, char类型适合存储短字符串(比用 varchar 更加节省空间)

3, char类型适合存储那些常常被更新的字符串 

 

如何存储时间类型:

datetime = YYYY-MM-DD HH:MM:SS 格式存储时间类型

datetime (6) = YYYY-MM-DD HH:MM:SS:微秒的  格式存储 时间类型 

datetime类型和 时区无关,内容并不会随着时区的变化而变化,占8个字节

datetime是比较通用型时间类型,通常均可以使用,它表示的时间范围也是很大的。

timestamp 时间戳,存储的是 1970年 1月1日 ,到目前的秒数 

显示的是 YYYY-MM-DD HH:MM:SS 格式 的,占用4个字节,比datetime更加节省空间,但是 timestamp只存储到 2038年的 时间范围,并且它的时间显示依赖于设置的时区,随着时区的改变而改变 。可是当行修改的时候,能够自动修改timestamp列的值 .

 

date 类型,格式送 YYYY-MM-DD  ,优势,占用的字节数 比使用的字节数,datetime , int 存储要少,

使用 date 只存储3个字节 ,存储范围也是很大的

使用date类型,还可使用 时间日期的函数进行计算 

time类型 格式是 HH:MM:SS 格式 的(能够指定宽度来存储微秒的数据)

存储时间日期的 注意事项:

1,不要使用字符串类型来存储日期时间类型(日期时间类型好比 字符串类型用的空间小)

2,日期时间类型在进行查找过滤时可使用日期来进行对比 

3,日期时间类型有很丰富的函数,能够方便对其进行日期的计算

4,若是要使用 int类型存储日期,那就使用 timestamp类型(若是在这个时间范围内,timestamp存储其实就是存储int的,只是显示的方式仍是之前那个样子而已)

 

如何为 InnoDB选择主键:

主键应该尽量的小(能够提升查询效率)

主键应该是顺序增加的(这样能够增长插入的效率,减小IO消耗,提升性能)

主键能够和业务主键不一样,为了保证惟一性,能够加惟一的索引

 

明确指定数据列的NOT NULL属性可以使MySQL在检索过程当中不用去判断数据列是不是NULL

 

尽可能使用 NOT NULL

NULL 类型比较特殊,SQL 难优化。虽然 MySQL NULL类型和 Oracle 的NULL 有差别,会进入索引中,但若是是一个组合索引,那么这个NULL 类型的字段会极大影响整个索引的效率。此外,NULL 在索引中的处理也是特殊的,也会占用额外的存放空间。
不少人以为 NULL 会节省一些空间,因此尽可能让NULL来达到节省IO的目的,可是大部分时候这会拔苗助长,虽然空间上可能确实有必定节省,却是带来了不少其余的优化问题,不但没有将IO量省下来,反而加大了SQL的IO量。因此尽可能确保 DEFAULT 值不是 NULL,也是一个很好的表结构设计优化习惯

 

LOB类型:强烈反对在数据库中存放 LOB 类型数据,虽然数据库提供了这样的功能,但这不是他所擅长的,咱们更应该让合适的工具作他擅长的事情,才能将其发挥到极致

 

尽可能使用TIMESTAMP类型,由于其存储空间只须要 DATETIME 类型的一半。对于只须要精确到某一天的数据类型,建议使用DATE类型,由于他的存储空间只须要3个字节,比TIMESTAMP还少。不建议经过INT类型类存储一个unix timestamp 的值,由于这太不直观,会给维护带来没必要要的麻烦,同时还不会带来任何好处。

 

非万不得已不要使用 TEXT 数据类型,其处理方式决定了他的性能要低于char或者是varchar类型的处理。定长字段,建议使用 CHAR 类型,不定长字段尽可能使用 VARCHAR,且仅仅设定适当的最大长度,而不是很是随意的给一个很大的最大长度限定,由于不一样的长度范围,MySQL也会有不同的存储处理。

.数字类型:非万不得已不要使用DOUBLE,不只仅只是存储长度的问题,同时还会存在精确性的问题。一样,固定精度的小数,也不建议使用DECIMAL,建议乘以固定倍数转换成整数存储,能够大大节省存储空间,且不会带来任何附加维护成本。对于整数的存储,在数据量较大的状况下,建议区分开 TINYINT / INT / BIGINT 的选择,由于三者所占用的存储空间也有很大的差异,能肯定不会使用负数的字段,建议添加unsigned定义。固然,若是数据量较小的数据库,也能够不用严格区分三个整数类型。

能够参考:  http://blog.csdn.net/aya19880214/article/details/45871733

 

BLOB和TEXT类型

         它们都是为存储大数据而设计的,BLOB是采用二进制/TEXT采用字符存储。MySQL不能将BLOB和TEXT列所有进行索引(只能作前面某长度的索引,所以在查询SQL时不能用LIKE前模糊匹配,那样就走不到索引了),也不能使用这些索引进行排序。

   技巧:使用枚举代替字符串类型,枚举能够把一些重复的字符串存储成一个预约义的集合,MySQL在存储枚举时很是紧凑,MySQL在列中保存值为枚举中的位置整数。枚举最很差的是字符串是固定的,添加或删除必须使用ALTER TABLE。所以对于将来会改变的字符串,使用枚举不是一个好主意,除非能接受在枚举末尾添加元素,因为枚举有一个映射转换过程,因此枚举虽然能减小存储空间,可是也会增长一些额外开销。

 

  1. 复合类型咱们通常用tinyint,更快的时间更省的空间以及更容易扩展
  2. 关于手机号,推荐用char(11),char(11)在查询上更有效率,由于手机号是一个活跃字段参与逻辑会不少。
  3. 一些经常使用字段举例
    姓名:char(20)
    价格:DECIMAL(7, 3)
    产品序列号:SMALLINT(5) unsigned
    文章内容: TEXT
    MD5: CHAR(32)
    ip: char(15)
    time: int(10)
    email char(32)

 

BLOB和TEXT类型,BLOB以二进制存储(一、0数据流,搞硬件编程的比较熟悉),TEXT以字符形式存储,都是用来存储很大数据的类型,注意,他们也是字符串类型,只是存储形式不一样。

BLOB和TEXT类型,在MySQL中会被做为对象处理,尽可能避免使用。

在使用text和blob字段类型时要注意如下几点,以便更好的发挥数据库的性能。

①BLOB和TEXT值也会引发本身的一些问题,特别是执行了大量的删除或更新操做的时候。删除这种值会在数据表中留下很大的"空洞",之后填入这些"空洞"的记录可能长度不一样,为了提升性能,建议按期使用 OPTIMIZE TABLE 功能对这类表进行碎片整理.

②使用合成的(synthetic)索引。合成的索引列在某些时候是有用的。一种办法是根据其它的列的内容创建一个散列值,并把这个值存储在单独的数据列中。接下来你就能够经过检索散列值找到数据行了。可是,咱们要注意这种技术只能用于精确匹配的查询(散列值对于相似<或>=等范围搜索操做符 是没有用处的)。咱们可使用MD5()函数生成散列值,也可使用SHA1()或CRC32(),或者使用本身的应用程序逻辑来计算散列值。请记住数值型散列值能够很高效率地存储。一样,若是散列算法生成的字符串带有尾部空格,就不要把它们存储在CHAR或VARCHAR列中,它们会受到尾部空格去除的影响。

合成的散列索引对于那些BLOB或TEXT数据列特别有用。用散列标识符值查找的速度比搜索BLOB列自己的速度快不少。

③在没必要要的时候避免检索大型的BLOB或TEXT值。例如,SELECT *查询就不是很好的想法,除非你可以肯定做为约束条件的WHERE子句只会找到所须要的数据行。不然,你可能毫无目的地在网络上传输大量的值。这也是 BLOB或TEXT标识符信息存储在合成的索引列中对咱们有所帮助的例子。你能够搜索索引列,决定那些须要的数据行,而后从合格的数据行中检索BLOB或 TEXT值。

④把BLOB或TEXT列分离到单独的表中。在某些环境中,若是把这些数据列移动到第二张数据表中,可让你把原数据表中 的数据列转换为固定长度的数据行格式,那么它就是有意义的。这会减小主表中的碎片,使你获得固定长度数据行的性能优点。它还使你在主数据表上运行 SELECT *查询的时候不会经过网络传输大量的BLOB或TEXT值。

 

 

还有就是对于 bit 类型的使用 ,若是是 bit(1) 就表明只有一位的数字,不是 0,就是 1 。

这样子对应java的类型就是 boolean布尔类型,能够用来进行布尔的判断。 true表明 1, 0表明 false 

好比能够 直接这样进行 使用   select *  from table where flage=true  ; 就能够查询出 flage(bit (1) ) =1 的全部数据了。若是是 bit(2) 就表明是2位了,不能存入 1位的,若是输入 1,那么默认就会存储是 01 两位的。

使用BIT数据类型保存位段值。BIT(M)类型容许存储M位值。M范围为1到64,BIT(1)定义一个了只包含单个比特位的字段, BIT(2)是存储2个比特位的字段,一直到64位。要指定位值,可使用b'value'符。value是一个用0和1编写的二进制值。例如,b'111'和b'100000000'分别表示7和128。若是为BIT(M)列分配的值的长度小于M位,在值的左边用0填充。例如,为BIT(6)列分配一个值b'101',其效果与分配b'000101'相同。

MySQL把BIT当作字符串类型, 而不是数据类型。当检索BIT(1)列的值, 结果是一个字符串且内容是二进制位0或1, 而不是ASCII值”0″或”1″。

一般咱们使用 bit(1) 来表示 布尔类型的,通常也是这样使用的。

 

总的来讲,进行数据库表的物理的 表的字段结构进行设计的时候呢,要权衡 好,查询 的效率问题和 咱们程序员使用的方便的角度。 不要太 追求极端了,要平衡好。并且我的认为,不要站在 数据库设计者的角度看问题,应该站在咱们程序员的角度看问题。好比 一些 字段类型,所有都使用  varchar  类型 又如何? 真的就对效率产生很大影响了? 若是效率过低了,能够进行 索引,或者一些表插入和查询而已就用用   myisam  存储引擎, 一些有事物的就用    innodb   等,增长数据库服务器,服务器的配置的。目前服务器又不贵了。并且 只有项目赚到了钱了,分库,分表,读写分离,分布式什么的, 那不是小意思。因此不太在乎,不要太完美,好用才是王道。提升开发效率才好,不要让开发 把至关大的部分的事情 浪费在 数据库方面去。

 

 

总结

其实在开发设置中,仍是结合 实际的状况来进行,特别是 公司里面没有 DBA 的状况下,对于数据设计来讲,固然是 尽可能按照 可使用 数据库 性能 最优的方式了,,可是实际开发中,咱们为了开发效率,是能够 不按照 规定来的,好比 主键就使用  varchar ;

  设计字段的时候,就是 默承认觉得 null , 由于随着业务发展,有些字段是能够为 null , 这样若是咱们 设计为 非 null,咱们不是插入的时候要插入 默认值? 影响开发效率 。。。等等总之,若是 对于中小公司,和 项目状况来 , 开发效率和后期维护成本才是王道,,,至于数据库的设计这块,不必,也不能有完美的 设计的。 再我看来, 目前出现了那么多数据库类型, 数据库就是 为了开发和维护服务的,毕竟 咱们是开发人员,不是专业的DBA ,,, 咱们不想 没事老加班,,为了 追求所谓的完美,没意义

相关文章
相关标签/搜索