殊不知,在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. 学习MVC之租房网站(六)-用户登录和权限控制

    在上一篇<学习MVC之租房网站(五)-权限.角色.用户管理>完成了权限.角色.用户的增删改查,现在将基于前面完成的内容,进行后台用户登录和权限控制功能的开发. 一.用户登录 用户登录涉及到 ...

  2. 使用Java语言开发微信公众平台(五)——获取access_token

    在前四期的文章中,我们分别学习了"环境搭建与开发接入"."文本消息的接收与响应"."被关注回复与关键词回复"."图文消息的发送与响 ...

  3. [C#学习]1.Hello World

    在很多时候我们都是被helloworld带入编程的世界的,所以这句话应该算是我们程序员最熟悉的一句话了把.所以在这里,那我也照样以helloworld为例子来引入我们的C#学习. 在往常的hellow ...

  4. (转载)提高mysql千万级大数据SQL查询优化30条经验(Mysql索引优化注意)

    1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索 ...

  5. vue.js 初体验— Chrome 插件开发实录

    欢迎大家关注腾讯云技术社区-博客园官方主页,我们将持续在博客园为大家推荐技术精品文章哦~ 作者:陈纬杰 背景 对于经常和动画开发打交道的开发者对于Animate.css这个动画库不会陌生,它把一些常见 ...

  6. Centos程序最小化后,窗口标签都消失找不到窗口的问题

    我是用的centos版本是CentOs 7. 在“顶部面板”或者 “底部面板” 右击选择“添加组件”),如下图所示: 在搜索框里输入“窗口列表”(window list),选中“窗口列表”即可.如下图 ...

  7. Zookeeper ZAB 协议分析

    前言 ZAB 协议是为分布式协调服务 ZooKeeper 专门设计的一种支持崩溃恢复的原子广播协议.在 ZooKeeper 中,主要依赖 ZAB 协议来实现分布式数据一致性,基于该协议,ZooKeep ...

  8. kotlin, 一种新的android平台一级开发语言

    最近看到一则科技新闻, 大致内容是google将kotlin语言作为android应用开发的一级语言, 与java并驾齐驱, 这是一个开发界的大事件大新闻, 连google的亲儿子go语言也没有这种待 ...

  9. UGUI ScrollRect 性能优化

    测试环境 操作系统:Windows8.1 开发工具:Unity5.5.2 1.问题描述,在实际开发过程中经常会使用ScrollRect实现滚动列表,当初次加载数据比较多的情形时,Unity3D会出现比 ...

  10. 开发一个Servlet示例

    Servlet响应请求步骤: Servlet是一个基于Java技术的Web组件,运行在服务器端,用户利用Servlet可以很轻松地扩展Web服务器的功能,使其满足特定的应用需要.Tomcat是一个常用 ...