殊不知,在N年前被奉为“圣经”的数据库设计3范式早就已经不完全适用了。这里我整理了一些比较常见的数据库表结构设计方面的优化技巧,希望对大家有用。

由于MySQL数据库是基于行(Row)存储的数据库,而数据库操作 IO 的时候是以 page(block)的方式,也就是说,如果我们每条记录所占用的空间量减小,就会使每个page中可存放的数据行数增大,那么每次 IO 可访问的行数也就增多了。反过来说,处理相同行数的数据,需要访问的 page 就会减少,也就是 IO 操作次数降低,直接提升性能。此外,由于我们的内存是有限的,增加每个page中存放的数据行数,就等于增加每个内存块的缓存数据量,同时还会提升内存换中数据命中的几率,也就是缓存命中率。

一、数据类型选择
     数据库操作中最为耗时的操作就是 IO 处理,大部分数据库操作 90%
以上的时间都花在了 IO 读写上面。所以尽可能减少 IO 读写量,可以在很大程度上提高数据库操作的性能。

我们无法改变数据库中需要存储的数据,但是我们可以在这些数据的存储方式方面花一些心思。下面的这些关于字段类型的优化建议主要适用于记录条数较多,数据量较大的场景,因为精细化的数据类型设置可能带来维护成本的提高,过度优化也可能会带来其他的问题:

1.数字类型:非万不得已不要使用DOUBLE,不仅仅只是存储长度的问题,同时还会存在精确性的问题。同样,固定精度的小数,也不建议使用DECIMAL,建议乘以固定倍数转换成整数存储,可以大大节省存储空间,且不会带来任何附加维护成本。对于整数的存储,在数据量较大的情况下,建议区分开
TINYINT / INT / BIGINT
的选择,因为三者所占用的存储空间也有很大的差别,能确定不会使用负数的字段,建议添加unsigned定义。当然,如果数据量较小的数据库,也可以不用严格区分三个整数类型。
2.字符类型:非万不得已不要使用
TEXT 数据类型,其处理方式决定了他的性能要低于char或者是varchar类型的处理。定长字段,建议使用 CHAR 类型,不定长字段尽量使用
VARCHAR,且仅仅设定适当的最大长度,而不是非常随意的给一个很大的最大长度限定,因为不同的长度范围,MySQL也会有不一样的存储处理。
3.时间类型:尽量使用TIMESTAMP类型,因为其存储空间只需要
DATETIME
类型的一半。对于只需要精确到某一天的数据类型,建议使用DATE类型,因为他的存储空间只需要3个字节,比TIMESTAMP还少。不建议通过INT类型类存储一个unix
timestamp 的值,因为这太不直观,会给维护带来不必要的麻烦,同时还不会带来任何好处。
4.ENUM &
SET:
对于状态字段,可以尝试使用 ENUM
来存放,因为可以极大的降低存储空间,而且即使需要增加新的类型,只要增加于末尾,修改结构也不需要重建表数据。如果是存放可预先定义的属性数据呢?可以尝试使用SET类型,即使存在多种属性,同样可以游刃有余,同时还可以节省不小的存储空间。
5.LOB类型:强烈反对在数据库中存放
LOB 类型数据,虽然数据库提供了这样的功能,但这不是他所擅长的,我们更应该让合适的工具做他擅长的事情,才能将其发挥到极致。在数据库中存储 LOB
数据就像让一个多年前在学校学过一点Java的营销专业人员来写 Java 代码一样。
二、字符编码
    
字符集直接决定了数据在MySQL中的存储编码方式,由于同样的内容使用不同字符集表示所占用的空间大小会有较大的差异,所以通过使用合适的字符集,可以帮助我们尽可能减少数据量,进而减少IO操作次数。

1.纯拉丁字符能表示的内容,没必要选择 latin1
之外的其他字符编码,因为这会节省大量的存储空间
2.如果我们可以确定不需要存放多种语言,就没必要非得使用UTF8或者其他UNICODE字符类型,这回造成大量的存储空间浪费
3.MySQL的数据类型可以精确到字段,所以当我们需要大型数据库中存放多字节数据的时候,可以通过对不同表不同字段使用不同的数据类型来较大程度减小数据存储量,进而降低
IO 操作次数并提高缓存命中率

三、适当拆分

    
有些时候,我们可能会希望将一个完整的对象对应于一张数据库表,这对于应用程序开发来说是很有好的,但是有些时候可能会在性能上带来较大的问题。

当我们的表中存在类似于 TEXT 或者是很大的
VARCHAR类型的大字段的时候,如果我们大部分访问这张表的时候都不需要这个字段,我们就该义无反顾的将其拆分到另外的独立表中,以减少常用数据所占用的存储空间。这样做的一个明显好处就是每个数据块中可以存储的数据条数可以大大增加,既减少物理
IO 次数,也能大大提高内存中的缓存命中率。

上面几点的优化都是为了减少每条记录的存储空间大小,让每个数据库中能够存储更多的记录条数,以达到减少 IO
操作次数,提高缓存命中率。下面这个优化建议可能很多开发人员都会觉得不太理解,因为这是典型的反范式设计,而且也和上面的几点优化建议的目标相违背。

四、适度冗余

为什么我们要冗余?这不是增加了每条数据的大小,减少了每个数据块可存放记录条数吗?
确实,这样做是会增大每条记录的大小,降低每条记录中可存放数据的条数,但是在有些场景下我们仍然还是不得不这样做:

被频繁引用且只能通过 Join
2张(或者更多)大表的方式才能得到的独立小字段
这样的场景由于每次Join仅仅只是为了取得某个小字段的值,Join到的记录又大,会造成大量不必要的
IO,完全可以通过空间换取时间的方式来优化。不过,冗余的同时需要确保数据的一致性不会遭到破坏,确保更新的同时冗余字段也被更新

五、尽量使用
NOT NULL

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

MySQL优化之表结构优化的5大建议(数据类型选择讲的很好)的更多相关文章

  1. 0709MySQL 数据库性能优化之表结构优化

    转自http://isky000.com/database/mysql-perfornamce-tuning-schema MySQL 数据库性能优化之缓存参数优化 MySQL数据库性能优化之硬件瓶颈 ...

  2. MySQL优化三 表结构优化

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

  3. MySQL优化之表结构优化的5大建议

    很多人都将 数据库设计范式 作为数据库表结构设计“圣经”,认为只要按照这个范式需求设计,就能让设计出来的表结构足够优化,既能保证性能优异同时还能满足扩展性要求殊不知,在N年前被奉为“圣经”的数据库设计 ...

  4. MySQL性能优化方法二:表结构优化

    原文链接:http://isky000.com/database/mysql-perfornamce-tuning-schema 很多人都将 数据库设计范式 作为数据库表结构设计“圣经”,认为只要按照 ...

  5. MySQL系列(三)--数据库结构优化

    良好的数据库逻辑设计和物理设计是数据库高性能的基础,所以对于数据库结构优化是很有必要的 数据库结构优化目的: 1.减少数据的冗余 2.尽量避免在数据插入.删除和更新异常 例如:有一张设计不得当的学生选 ...

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

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

  7. MySQL 对比数据库表结构

    200 ? "200px" : this.width)!important;} --> 介绍 本章主要介绍怎样对比数据库的表结构的差异,这里主要介绍使用mysqldiff工具 ...

  8. mysql在线修改表结构大数据表的风险与解决办法归纳

    整理这篇文章的缘由: 互联网应用会频繁加功能,修改需求.那么表结构也会经常修改,加字段,加索引.在线直接在生产环境的表中修改表结构,对用户使用网站是有影响. 以前我一直为这个问题头痛.当然那个时候不需 ...

  9. mysql 在线修改表结构工具 gh-ost

    gh-ost使用测试: gh-ost -host='192.168.65.136' -user=root -password='' -database='haha' -chunk-size=10000 ...

随机推荐

  1. LINQ TO XML初步了解

    最近简单的学习了一下LINT TO XML,写篇博客在这,方便以后查看~~ 1.常用到的类   XmlDocument --    文档(xml文件)     XmlElement    --     ...

  2. 如何有效快速提高Java服务端开发人员的技术水平?

    我相信很多工作了3-5年的开发人员都会经常问自己几个问题: 1.为什么总是感觉技术没有质的提高? 2.如何能够有效和快速的提高自身的技术水平? 3.如何进入到一个牛逼的大公司,认识牛逼的人? 这篇文章 ...

  3. js里变量的作用域

    一.在js中,变量的定义并不是以代码块作为作用域的,而是以函数作为作用域.也就是说,如果变量是在某个函数中定义的,那么,它在函数以外的地方是不可见的.但是,如果该变量是定义在if或者for这样的代码块 ...

  4. C#图像处理——ImageProcessor

    这是个老生常谈的话题,需求实在太多,而且也较简单,写此文也是因为几个月没写技术文章了,权当为下一步开个头.我之前也做过很多此类项目,但是就我自己来说每次处理方式还都不一样,有用OpenCV的,有用Ma ...

  5. Linux-进程描述(5)之进程环境

    main函数和启动例程 当内核使用一个exec函数执行C程序时,在调用main函数之前先调用一个特殊的启动例程,可执行程序将此例程指定为程序的起始地址.启动例程从内核获取命令行参数和环境变量,然后为调 ...

  6. (原创)看我用各种姿势在手机和PC查看到连接到的wifi密码

    今天一个女神来我家做客,她问我WiFi密码,然而我却奇迹般的忘记了(特么的当时心里一万个草泥马踏过去),让我在她面前尴尬求子的,所以为了防止你们也出现这种情况,我特地把各种方法整理了一下,那么感兴趣的 ...

  7. Struts2框架的基本使用(三)

    上篇 Struts2框架的基本使用(二)介绍了Action和result的相关配置操作,本篇接着介绍剩下的异常处理机制和Convention插件的使用.下篇文章介绍的是Struts2框架中标签库的使用 ...

  8. Java设计模式随笔

    大家都知道Java23种设计模式,大神总结如下: 创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. 结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式.桥接 ...

  9. python课程day_2-->总结-->字符串功能

    =======================课程大纲=======================> 基本数据类型 - 整数 - 布尔值 - 字符串 - 列表 - 元组 - 字典 - 集合 工 ...

  10. 实现javascript下的模块组织

    前面的话 java有类文件.Python有import关键词.Ruby有require关键词.C#有using关键词.PHP有include和require.CSS有@import关键词,但是对ES5 ...