学习MySQL,怎么能不会数据类型和schema优化


学习MySQL,怎么能不会数据类型和schema优化文章插图
作者 | 草捏子
来源 | 草捏子(ID:chaycao)
头图 | CSDN 下载自东方IC
本文就数据类型和schema方面的优化进行介绍 。
学习MySQL,怎么能不会数据类型和schema优化文章插图
学习MySQL,怎么能不会数据类型和schema优化文章插图
选择优化的数据类型
MySQL支持的数据类型有很多 , 而如何选择出正确的数据类型 , 对于性能是至关重要的 。 以下几个原则能够帮助确定数据类型:

  1. 更小的通常更好
    应尽可能使用可以正确存储数据的最小数据类型 , 够用就好 。 这样将占用更少的磁盘、内存和缓存 , 而在处理时也会耗时更少 。
  2. 简单就好
    当两种数据类型都能胜任一个字段的存储工作时 , 选择简单的那一方 , 往往是最好的选择 。 例如整型和字符串 , 由于整型的操作代价要小于字符 , 所以当在两者之间选择时 , 选择整型通常能够获得更好的性能 。
  3. 尽量避免
    当列可为时 , 对于MySQL来说 , 在索引和值比较等方面需要做更多的工作 , 虽然对性能的影响不是很大 , 但也应尽量避免设计为可为 。
除了以上原则 , 在选择数据类型时 , 需遵循的步骤:首先确定合适的大类型 , 例如数据、字符串、时间等;然后再选择具体的类型 。 下面将讨论大类型下的一些具体类型 , 首先是数字 , 有两种类型:整数和实数 。
一、整数类型整数类型和所占用的空间如下:
整数类型空间大小(bit)TINYINT8SMALLINT16MEDIUMINT24INT32BIGINT64整数类型所能存储的范围和空间大小有关:-2^(N-1)至2^(N-1)-1 , 其中N为空间大小的位数 。
整数类型具有UNSIGNED的可选属性 , 当声明时 , 表示不允许负数 , 则存储范围变为:0至2^(N)-1 , 扩大了一倍 。
在MySQL中 , 还可以为整数类型指定宽度 , 例如INT(1) , 但这样的意义并不大 , 并不会限制值的合法范围 , 仍能存储-2^31至2^31-1的值 , 所影响的是与MySQL的交互工具显示字符的个数 。
二、实数类型实数类型的对比如下:
实数类型空间大小(Byte)取值范围计算精度FLOAT4负数:-3.4E+38~-1.17E-38;非负数:0、1.17E-38~3.4E+38近似计算DOUBLE8负数:-1.79E+308~-2.22E-308;非负数:0、2.22E-308~1.79E+308
近似计算DECIMAL与精度有关同DOUBLE精确计算从上面可以看出 , FLOAT和DOUBLE都有固定的空间大小 , 但同时由于是使用标准的浮点运算 , 所以只能近似计算 。 而DECIMAL则可以实现精确计算 , 与此同时占用的空间会相较更大 , 所耗费的计算开销也更多 。
DECIMAL所占空间大小与指定的精度有关 , 例如DECIMAL(M,D):
  • M为整个数字的最大长度 , 取值范围为[1, 65] , 默认值为10;
  • D为小数点后的长度 , 取值范围为[0, 30] , 且D <= M , 默认值为0 。
MySQL在存储DECIMAL类型时会作为二进制字符串存储 , 每4个字节存9个数字 , 当不足9位时 , 数字的占用空间如下:
数字个数占用空间(Byte)1、213、425、637、84小数点前后将分别存储 , 同时小数点也要占1个字节 。 下面举两个计算的例子:
  1. DECIMAL(18, 9):整数部分长度为9 , 占用4个字节 。 小数部分长度为9 , 占用4个字节 。 同时加上小数点1个字节 , 则总共占用9个字节 。
  2. DECIMAL(20, 9):整数部分长度为14 , 占用7(4+3)个字节 。 小数部分长度为9 , 占用4个字节 。 同时加上小数点1个字节 , 则总共占用12个字节 。
可以看出DECIMAL的空间占用还是很大的 , 因此只有当需要对小数进行精确计算时 , 才需要使用DECIMAL 。 除此之外 , 我们还可以使用BIGINT代替DECIMAL , 例如需要保证小数点后5位的计算 , 可以将值乘上10的5次方后作为BIGINT存储 , 这样能同时避免浮点存储计算不精确和DECIMAL精确计算代价高的问题 。
三、字符串类型最常用的字符串类型当属 VARCHAR 和 CHAR 。 VARCHAR 作为可变长字符串 , 会使用1或2个额外字节记录字符串的长度 , 当最大长度未超过255时 , 只需1个字节记录长度 , 超过255 , 则需2个字节 。 VARCHAR 的适用场景:
  1. 最大长度比平均长度大很多;
  2. 列的更新少 , 避免碎片;
  3. 使用复杂的字符集 , 如UTF-8 , 每个字符能使用不同的字节存储 。
CHAR 则为定长字符串 , 根据定义的字符串长度分配足够的空间 , 适用场景:
  1. 长度短;