Mysql数据类型的优化,如何选择合适的数据类型呢?——高性能Mysql(第四章笔记1)

咱在建表的时候,总是很疑惑,这个键值到底选哪种类型好呢?不同的类型有什么讲究吗?今天咱来掰扯掰扯。

选择数据类型的一般性偏好

1、在确保没有低估需要储存的值的范围下,选择占用越小的数据类型。
这很容易理解,谁都不喜欢啰嗦的话语,计算机也一样,能用一句话说完,为什么要说上十句话呢。

2、简单就好
如果该列需要排序,优先选用数据库里已内置的数据类型。比如储存时间,大家应该都会去使用datatime,timestamp这种,而不会使用字符串来储存。因为整型比字符操作代价更低(更快)。还有一个例子是用整型储存ip地址。

3、尽量避免 null
这指的是要排序的列里,最好不要使用null值,如果只是查询不排序,那无所谓了。不建议在可为空的列上,做索引。

知道了上述几个大前提,咱来看看具体的类型选择。

数字有两种类型:整数,实数(有小数点的)

整数类型
类型名称储存空间 (位)
TINYINT8
SMALLINT16
MEDIUINT24
INT32
BIGINT64

显示范围跟是否带符号有关,这个是可选的

咱们的选择,只是决定Mysql如何在内存和磁盘中储存数据。然而整数计算一般使用64位的BIGINT,即使在32位环境也是如此。(一些聚合函数除外,它们使用DECIMAL或DOUBLE进行)

实数类型

实数嘛,引入了小数点的概念。DECIMAL可以储存比BIGINT更大的数。该类型用于储存精确的小数。

FLOAT,DOUBLE这种浮点数的计算方式,跟各平台有关,就不赘述了。

CPU不支持DECIMAL的直接计算,但是支持原生浮点运算。早期Mysql版本,DECIMAL只是一种储存格式,计算中会转化为DOUBLE类型。

类型名称储存空间 (字节)
FLOAT4
DOUBLE8
DECIMAL最多64

在数据量比较大、小数位固定的情况下,可以考虑用BIGINT替代DECIMAL,比如0.01*100(倍数)=存1

字符串类型

有CHAR,VARCHAR,BLOB,TEXT这几种类型

先来看CHAR与VARCHAR

这两货在内存磁盘中的储存方式可能是不一样的!

VARCHAR 顾名思义,可变长度字符串,因为是可变长,咱肯定要知道这个字符串到底有多长,才能把它准确的取出来吧。所以VARCHAR类型的值都会有1或者2个字节来表示值到底有多长。1字节8位,最多能表示255字符数(注意呀,不是字节数),所以字符数少于255的,就用一个字节来表示长度,超过的话,就用2个字节。咱也能看出VARCHAR的上限有多大了,2^16-1=65 535。InnoDB会把过长的VARCHAR储存为BLOB的,真是灵活呀!

咱可以想象到,因为储存的字符串的长度是可变的,如果要改变存储的字符串的值,是一件相当麻烦的事情。不同的引擎会有不同的操作,这里就不赘述了。

如果字符串的最大长度比平均长度大很多,并且更新很少的话,那么选用VARCHAR是很合适哒。

嚯嚯,VARCHAR是变长的,CHAR是定长的!

是不是有种链表跟数组的既视感,原理是相通的。

需要注意的一点是,CHAR类型会将值屁股后面的空格去除掉。比如“string3 ”会存成“string3”。这是在服务器层面做的操作,不是存储引擎干的,所以所有的引擎在这一点是一样的。

跟VARCHAR,CHAR类似的还有BINARY,VARBINARY

这两货存的是二进制字符串(字节码),不是字符

赶紧去查了下啥是字节码。
什么是字节码
好了,知道了,不是人看的。

因为是给机器看的。所以比较起来的话,这两种类型会更快

问题来了,为啥咱现在要抠抠搜搜的,一点也不大方?因为Mysql通常会分配固定大小的内存块来保存内部值。比如内存临时表排序

行行行,咱以后一定勤俭持家,不浪费一点存储空间!

BLOB和TEXT

这题我会!TEXT是字符类型的,BLOB是二进制类型的!

字符类型二进制类型
TINYTEXTTINYBLOB
SMALLTEXT(叫TEXT也行)SMALLBLOB(叫BLOB也行)
MEDIUMTEXTMEDIUM BLOB
LONGTEXTLONGBLOB

这两货太长了,还是不要跟行在一起了,一般会给它安排一个外部空间,存在那边。行这边只留一个指针!

Mysql对这两种类型进行排序的话,只对每行最前max_sort_length字节进行排序,(ORDER BY SUBSTRING(column,length),加上这句sql也是妥妥的)用小脑袋想一想也明白,怎么可能对那么~长的值进行整体排序呢!

枚举类

虽然(ENUM关联ENUM)比(VARCHAR关联VARCHAR)快,但是平时咱都不用这个类型的啊。再快也没有整型快吧。枚举类型咱都是写在后端代码那边的,存的是整型,略过略过。

日期和时间类型

日期,很常用的数据类型呢。咱得知道,Mysql的最小时间粒度为,MariaDB才支持微秒级别的。

Mysql有两种日期类型,DATETIME和TIMESTAMP,这两货有啥不同呢

DATETIMETIMESTAMP
1001年到9999年,精度为秒1970年1月1日午夜以来的,秒数,最迟到2038-01-19 03:14:07
8字节4字节
格式:YYYYMMDDHHMMSS的整数秒数啊,用整型不过分吧
输入咋样输出就咋样不同时区不同哦亲

现在2021年了,懂我的意思吧,留给TIMESTAMP的时间,不多了。

位数据类型

不是我说,这种数据类型也太抠了吧,精确到bit,一般最好不要用吧。不过有一种情况比较适合。那就是表示是否拥有权限的时候。比如一个字节01010101,1表示有这种权限,0表示没有,那是挺好的,一个值可以表示好多种权限呢,但是得约定好,每位代表啥。

选择标识符

可以和其他表产生联系的列,常见的比如订单号(order_id),活动id什么的,最好使用整数类型,比较快,也可以自增,比较方便。

最好不要用随机值,因为这样会使得相邻的行的分步很分散。查找起来,新增起来,查找相邻行也很慢。

原文:如果存储UUID值,则应该移除“-”,更好的做法是,用UNHEX()函数转化UUID值为16字节的数字,并存储在一个BINARY(16)列中。检索时可以通过HEX()函数来格式化为十六进制格式。

听上去是个不错的方法呢。

特殊类型数据

IPv4地址不是字符唉,它们实际上是32位无符号整数。所以应该用无符号整数存储IP地址。Mysql提供了INET_ATON()函数
【功能是将一个字符串IP地址转换为一个32位的网络序列IP地址】
和INET_NTOA()函数
【功能是将网络地址转换成“.”点隔的字符串格式】来表示这两种表示方法的转换。

最后的最后

这里的长度是啥

我们有在Navicat看到过这种长度的选择

其实选择这种不会影响实际的存储空间大小(字符串出除外)

引用:参考这个可选的宽度规格说明是用于在数值显示时,对某些值的宽度短于该列宽度的值进行左填补显示的,而不是为了限制在该列中存储值的宽度,也 不是为了限制那些超过该列指定宽度的值的可被显示的数字位 数。

还有,小心自己写的数据迁移的脚本,注意格式的转换,不然良好的设计就要前功尽弃了。

希望大家能从这篇笔记里有所收获,解答一些疑惑~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

rgbhi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值