2 MySQL 数据库设计的“奥秘”

【主题】逻辑设计:数据类型与 Schema

所谓“万丈高楼平地起”,一个稳固的建筑离不开扎实的基础。同样,良好的的「逻辑设计」「物理设计」是数据库高性能的基石。

本文的主要内容总结了一张图,你可以点击查看。

我们需要根据系统需要执行的 SQL 语句设计 schema,这往往权衡各种因素。

[idea]瞧!权衡和取舍不仅仅在系统设计、方案设计时处处体现其价值,在数据库表设计也同样如此。

举个例子,反范式设计可以加快某些类型查询,但可能会使另一些类型查询变慢。如增加汇总表可以优化查询,但这些表维护成本可能很高。

首先,让我们一起来看下 MySQL 的数据类型,这是我们设计数据表前需要事先掌握的。

如何选择优化的数据类型?

MySQL 支持的数据类型很多,为了做出更好的选择,我们来看几个简单的原则:

1.更小的通常更好

尽量使用可以正确存储数据的最小数据类型

优点:

  • 占用更少的磁盘、内存和 CPU 缓存
  • 处理时需要 CPU 周期更少

缺点:

  • 但是要确保没有低估存储值范围

2.简单就好

简单数据类型需要更少的 CPU 周期。

比如整型比字符串代价低(字符串有字符集和校对规则)。

3.尽量避免 NULL

NULL 列对 MySQL 更难优化,因为为 NULL 的列使得索引、索引统计和值比较都更复杂;并且占用更多存储空间。

todo 为什么占用更多存储空间?

推荐步骤

步骤1:确定合适的大类型

如数字、字符串、时间等。

步骤2:选择具体类型

同类型下只是存储的长度、范围、允许的精度、需要的物理空间(磁盘、内存)不同。

数据类型概览

1.整数类型

有两种类型的数字:「整数」「实数」

整数有很多种,如:TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT,分别使用 8,16,24,32,64 位存储空间。

  • 有可选的 UNSIGNED 属性,表示不允许负值。

  • 还可以指定宽度

    例如 INT(11),它不会限制值的合法范围,只是规定了 MySQL 的一些客户端显示字符的个数。

    INT(1) 和 INT(11) 是相同的。

2.实数类型

即带有小数部分的数字。MySQL 既支持精确类型,也支持不精确类型。

  • 可以指定需要的精度

FLOAT 和 DOUBLE 类型使用浮点运算进行近似计算。

DECIMAL 类型用于存储精确的小数。使用场景:尽量只有对小数需要精确计算时才使用,因为需要额外的存储空间和计算开销。

数据量比较大时,可以使用 BIGINT 代替 DECIMAL,对应单位乘以相应倍数即可。

3.字符串类型

VACHAR 和 CHAR 类型

VACHAR
  • 比定长类型更节省空间,因为它只使用必要的空间(如字符串越短使用空间越少)。

  • 需要使用 1(<=255) 或 2(>255) 个额外字节记录字符串长度。

  • 由于变长,Update 可能使行变得比原来更长,容易产生碎片

    如 InnoDB 需要页分裂使得行可以放到页内。

适合 VACHAR 的场景:

  • 最大长度比平均长度大得多
  • 列的更新很少
  • 使用了像 UTF-8 这样的复杂字符集
CHAR
  • 定长,会根据需要填充空格

适合 CHAR 的场景:

  • 存储很短的字符串或所有值接近同一个长度
  • 经常变更数据,不易产生碎片(因为定长不会页分裂)

建议:最好的策略是只分配真正需要的空间

todo Vachar(5) 和 Vachar(200) 又什么区别?空间开销一样吧?

BLOB 和 TEXT 类型

适合场景:存储很大的数据,前者使用二进制,后者使用字符存储。

特殊之处:MySQL 把 BLOB 和 TEXT 值当作独立对象处理,值太大时会使用专门的“外部”存储区域存储,在行内存储指针指向外部实际值。

[idea]这个设计在程序开发中也可以使用,有时一些大属性占用存储较多但使用频率较低,可以单独存储在其他地方,通过指针进行引用,从而使得该对象更小。

不能将 BLOB 和 TEXT 列全部长度索引,不能用这些索引消除排序。

如果 Explain 执行计划的 Extra 列包含“Using temporary”,说明这个查询使用了「隐式临时表」

使用枚举(ENUM)代替字符串类型

优点:存储枚举时非常紧凑,节约空间

MySQL 内部将每个值在列表中位置保存为整数,在表的 .frm 文件中保存“数字-字符串”映射关系的“查找表”。

所以,使用数字作为枚举常量,这种双重性容易导致混乱。建议尽量避免这么做

例如 ENUM('1','2',3'')

️枚举字段是按照内部存储整数而不是定义的字符串数字排序。

缺点:

  • 字符串列表是固定的,如果未来要改变枚举值则不适合
  • 枚举值转为整数值保存有开销

建议通用设计实践:在“查找表”时采用整数主键而避免采用字符串的值进行关联,因为性能更好。


END

MySQL 数据库设计的“奥秘”的更多相关文章

  1. mySql 数据库设计原则

    mysql数据库设计原则: 必须使用InnoDB存储引擎 解读:支持事务.行级锁.并发性能更好.CPU及内存缓存页优化使得资源利用率更高 禁止使用存储过程.视图.触发器.Event 解读:高并发大数据 ...

  2. mysql数据库设计规则总结

    MySQL数据库设计总结   规则1:一般情况可以选择MyISAM存储引擎,如果需要事务支持必须使用InnoDB存储引擎. 注意:MyISAM存储引擎 B-tree索引有一个很大的限制:参与一个索引的 ...

  3. mysql数据库设计

    2.MySQL之选择字段数据类型 1.http://blog.itpub.net/29660208/viewspace-1208352/ 3.http://www.cnblogs.com/HondaH ...

  4. MySQL数据库设计复习笔记及项目实战

    最近手头上有3个项目开动,其他2个都是从底层开始的,一个已经开始了一段时间的了,在小城市小团队开发的条件下,都没有专门的DBA来做数据库的设计和维护,往往都是开发人员顶上,可是看了很多的数据库的设计, ...

  5. 互联网产品mysql数据库设计总结

    mysql数据库性能不比oracle数据库,所以设计上,和oracle有一些不同.下面总结一些互联网产品的数据库设计. 1.主键 主键可以使用bigint(20) unsigned也可以使用varch ...

  6. 范式及其在mysql数据库设计中的应用

    一.什么是范式 1.1.范式:Normal Format,是离散数学的知识,是为了解决数据的存储与优化而提出来的.要求存储数据后,凡是能够通过关系寻找出来的数据,坚决不再重复存储,终极目标是为了减少数 ...

  7. MYSQL数据库设计之字段选择原则

    关于字段的选择其实很多地方都有进行详细的介绍,我这里只写一下我在使用过程中的心得感受.如果想要全面的了解的话,大家可以去看高性能MYSQL这一本书籍,里面有一章节介绍的特别全面,基本涉及MYSQL中全 ...

  8. mysql 数据库设计(转)

    本规范适用于mysql 5.1或以上版本使用 数据库范式 第一范式(1NF)确保每列保持原子性 第一范式(1NF):数据库表的每一列都是不可分割的原子数据项,而不能是集合,数组,记录等非原子数据项. ...

  9. MySQL数据库设计常犯的错以及对性能的影响

    1.过分的反范式化为表建立太多的列 我们在设计数据库的结构时,比较容易犯的第一个错误就是对表进行了过分的反范式化的设计,这就容易造成了表中的列过多,虽然说Mysql允许为一个表建立很多的列,但是由于M ...

随机推荐

  1. MySQL binlog_ignore_db 参数最全解析

    前言: 经过前面文章学习,我们知道 binlog 会记录数据库所有执行的 DDL 和 DML 语句(除了数据查询语句select.show等).注意默认情况下会记录所有库的操作,那么如果我们有另类需求 ...

  2. OO随笔之追求完美的第三单元——初试JML

    前言 这一章的JML比较简单,那么大家的关注点自然地移到了性能优化上.于是大家一股脑地去利用各种数据结构去做时间上的优化(当然很多人最后还是倒在了正确性上),故称追求完美的一单元.当然这也是得益于JM ...

  3. 21.File和IO流

    IO就可以对文件进行读写 File表示要读写的文件在哪,也可以对文件进行创建,删除等操作 小结: IO流是什么? 1.可以将数据从本地文件中读取出来 2.可以将数据从内存保存到本地文件 File类时什 ...

  4. [Qt] Librecad 源码分析

    libraries jwwlib libdxfrw:一个免费的C++库,用于读写文本格式或二进制格式的DXF文件(C++ library to read and write DXF/DWG files ...

  5. 在写脚本时,在一开始(Shebang 之后)就加上这一句,或者它的缩略版: set -xeuo pipefail

    编写可靠 bash 脚本的一些技巧 腾讯技术工程 ​ 已认证的官方帐号   1,254 人赞同了该文章 写过很多 bash 脚本的人都知道,bash 的坑不是一般的多. 其实 bash 本身并不是一个 ...

  6. Deepin/Uos系统更新源失败。提示:E: 仓库 “http://packages.chinauos.cn/uos eagle

    Deepin/Uos系统更新源失败.提示:E: 仓库 "http://packages.chinauos.cn/uos eagle InRelease" 没有数字签名 起因是在Uo ...

  7. split命令_Linux split命令:切割(拆分)文件

    <Linux就该这么学>是一本基于最新Linux系统编写的入门必读书籍,内容面向零基础读者,由浅入深渐进式教学,销量保持国内第一,年销售量预期超过10万本.点此免费在线阅读. 15 分钟之 ...

  8. Shell脚本 /dev/null 2>&1详解

    Shell脚本---- /dev/null 2>&1详解   1.可以将/dev/null看作"黑洞". 它非常等价于一个只写文件. 所有写入它的内容都会永远丢失. ...

  9. Oracle中Table函数简单应用实例

    说明 表函数可接受查询语句或游标作为输入参数,并可输出多行数据. 该函数可以平行执行,并可持续输出数据流,被称作管道式输出. 应用表函数可将数据转换分阶段处理,并省去中间结果的存储和缓冲表. 优势 1 ...

  10. Stream中的Peek操作

    1.引言 如果你试图对流操作中的流水线进行调试, 了解stream流水线每个操作之前和操作之后的中间值, 该如何去做? 首先我们看一个例子, 使用forEach将流操作的结果打印出来. 1 /** 2 ...