MySQL 8.0 数据类型小结

备注:测试数据库版本为MySQL 8.0

这个blog我们来聊聊MySQL支持的数据类型

一.数字类型

类型存储(字节)最小(有符号)最大(有符号)最小(无符号)最大(无符号)描述
BIT(M)(m+7)/8位值类型。M表示每个值的位数,从1到64.如果M省略,默认是1。比如bit(8)存储888变为00000111
TINYINT(M)1-1281270255
SMALLINT(M)2-3276832767065535
MEDIUMINT(M)3-83886088388607016777215
INT,INTEGER(M)4-2147483648214748364704294967295
BIGINT(M)8-2^632^63 -102^64
DECIMAL变长(0-4个字节)M为总位数(精度),D为小数点后的位数(刻度)。如果D为0,则值没有小数部分。最大(M)是65。最大(D)为30.如果省略D,D的默认值为0,。如果省略M,M的默认值为10. NUMBERIC的实现是DECIMAL
NUMBERIC变化同上
FLOAT(M,D)4M是总位数,D是小数点后面的位数。如果M和D省略,则将值存储到硬件允许的限制。单精度浮点精确到7位小数。
正区间- [ –3.402823466E38 , –1.175494351E-38 ]
负区间-[ 1.175494351E-38 , 3.402823466E38]
DOUBLE(M,D)8M是总位数,D是小数点后面的位数。如果M和D省略,则将值存储到硬件允许的限制。单精度浮点精确到15位小数。
正区间-[ –1.7976931348623157E308,–2.2250738585072014E-308 ]
负区间-[ 2.2250738585072014E-308 , 1.7976931348623157E308 ]
BOOL,BOOLEAN1TINYINT(1)的同义词

总结:
1.不允许负数
整数类型有可选的UNSIGNED属性,表示不允许存负值,这大概可以使整数的上限提高一倍。
如: TINYINT UNSIGNED

2.如何选择合适的数值类型
1.整数类型
例如枚举类的, 选择 tinyint、smallint即可,节省磁盘空间就是优化。
其它的业务相关表,例如用户表、订单表 可以选择用 int类型。
虽然int类型不支持小数,但是例如金额这个,可以通过调整单位,例如单位为分,这样就可以存小数金额了
对于一些大的日志表、分布式ID之类的,可以选择bigint类型

2.小数类型
对于需要存储小数的场景而言,使用decimal(m,d)
m代表总的位数,d代表小数位,整数位为m-d

create table t_decimal(id  decimal(7,4));
-- 小数位不够会自动填0
insert into t_decimal values (123.456);
-- 这个是正常的插入方法
insert into t_decimal values (123.4561);
-- 整数为超过限制 报错
insert into t_decimal values (1230.4561);
-- 小数位超过限制 报错
insert into t_decimal values (1230.45612);

执行记录:

mysql> create table t_decimal(id  decimal(7,4));
Query OK, 0 rows affected (0.03 sec)

mysql> -- 小数位不够会自动填0
mysql> insert into t_decimal values (123.456);
Query OK, 1 row affected (0.00 sec)

mysql> -- 这个是正常的插入方法
mysql> insert into t_decimal values (123.4561);
Query OK, 1 row affected (0.00 sec)

mysql> -- 整数为超过限制 报错
mysql> insert into t_decimal values (1230.4561);
ERROR 1264 (22003): Out of range value for column 'id' at row 1
mysql> -- 小数位超过限制 报错
mysql> insert into t_decimal values (1230.45612);
ERROR 1264 (22003): Out of range value for column 'id' at row 1
mysql>
mysql> select * from t_decimal;
+----------+
| id       |
+----------+
| 123.4560 |
| 123.4561 |
+----------+
2 rows in set (0.00 sec)

3.浮点数
浮点数会存在一定的精度的缺失,但是可以应用于科学计算,性能会比整数和小数类都要快。

二.日期时间类型

类型存储(字节)范围格式用途
DATE31000-01-01/9999-12-31YYYY-MM-DD日期值
TIME3‘-838:59:59’/‘838:59:59’HH:MM:SS时间值或持续时间
YEAR11901/2155YYYY年份值
DATETIME81000-01-01 00:00:00/9999-12-31 23:59:59YYYY-MM-DD HH:MM:SS混合日期和时间值
TIMESTAMP41970-01-01 00:00:00/2038YYYYMMDD HHMMSS混合日期和时间值,时间戳

关于时间类型的选择:
1.如果只存年,用YEAR类型
2.如果只存年月日,用DATE
3.如果需要存年月日时分秒,用TIMESTAMP
不要被这个2038年给吓到了,而不用TIMESTAMP,其实更节约存储空间,且能容纳时区信息
4.不用将TIMESTAMP转换为数值
FROM_UNIXTIME() – 把数值转换为时间戳
UNIX_TIMESTAMP() – 把时间戳转换为数值

转换感觉是节省了空间,不过处理起来非常的不方便,不推荐使用

在这里插入图片描述

三.字符类型

CHAR和VARCHAR类型

类型存储(字节)范围用途
CHAR(M)M0 - 255存储定长的字符
VARCHAR(M)VARCHAR(10) 实际存储3个字符,1个字节来存储长度,总共占4字节
VARCHAR(1000) 实际存储3个字符,2个字节来存储长度,总共占5字节
不同的存储引擎可能存在一定的差异
0-65536存储可变长度的字符串

1.类型选择问题
很多时候,开发同事为了方便,直接用varchar(200) 来存储字符,不考虑实际需求。
这样做,存在诸多弊端。
如果是md5密码这样的定长字段,如果用varchar类型,会浪费一定的存储空间。
如果存储的字符只有5个,而这时都用varchar(200),感觉存储空间是一样的。但是程序端读取的时候,varchar(200)会消耗更多的内存。

2.变长字符的更新问题
InnoDB存储引擎
varchar由于是变长,遇到更新的时候,如果比原先的长度长很多,这个时候页的空间不够,会分裂页,此时会比较消耗性能

3.定长字符神奇的空格问题

-- char类型,string3末尾的空格莫名的不见了
create table char_test( char_col char(10));
insert into char_test(char_col) values ('string1'),('   string2'),('string3   ');
select * from char_test;
select concat("'",char_col,"'") from char_test;
-- 换成varchar类型,就不会出现这个问题
drop table char_test;
create table char_test( char_col varchar(10));
insert into char_test(char_col) values ('string1'),('   string2'),('string3   ');
select concat("'",char_col,"'") from char_test;

执行记录:

mysql> create table char_test( char_col char(10));
Query OK, 0 rows affected (0.04 sec)

mysql> insert into char_test(char_col) values ('string1'),('   string2'),('string3   ');
Query OK, 3 rows affected (0.02 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> select * from char_test;
+------------+
| char_col   |
+------------+
| string1    |
|    string2 |
| string3    |
+------------+
3 rows in set (0.00 sec)

mysql> select concat("'",char_col,"'") from char_test;
+--------------------------+
| concat("'",char_col,"'") |
+--------------------------+
| 'string1'                |
| '   string2'             |
| 'string3'                |
+--------------------------+
3 rows in set (0.00 sec)

mysql>
mysql>
mysql> drop table char_test;
Query OK, 0 rows affected (0.03 sec)

mysql> create table char_test( char_col varchar(10));
Query OK, 0 rows affected (0.02 sec)

mysql> insert into char_test(char_col) values ('string1'),('   string2'),('string3   ');
Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> select concat("'",char_col,"'") from char_test;
+--------------------------+
| concat("'",char_col,"'") |
+--------------------------+
| 'string1'                |
| '   string2'             |
| 'string3   '             |
+--------------------------+
3 rows in set (0.00 sec)

BLOB和TEXT类型

类型描述
TINYBLOB最大长度255(2^8-1),使用1字节前缀存储长度信息
BLOB最大长度65,535(2^16-1),使用2字节前缀存储长度信息
MEDIUMBLOB最大长度16,777,215(2^24-1),使用3字节前缀存储长度信息
LONGBLOB最大长度(2^32-1)或4GB,使用4字节前缀存储长度信息
TINYTEXT最大长度255(2^8-1),使用1字节前缀存储长度信息
TEXT最大长度65,535(2^16-1),使用2字节前缀存储长度信息
MEDIUMTEXT最大长度16,777,215(2^24-1),使用3字节前缀存储长度信息
LONGTEXT最大长度(2^32-1)或4GB,使用4字节前缀存储长度信息

BLOB是SMALLBLOB的同义词
TEXT是SMALLTEXT的同义词

MySQL把每个BLOB和TEXT当做一个独立的对象处理。
当BLOB和TEXT值太大时,InnoDB会使用专门的外部存储区域来进行存储,此时每个值在行内需要1-4个值存储一个指针,然后在外部存储区域存储实际的值

BLOB和TEXT家族之间仅有的不同是BLOB类型存储的是二进制数据,没有排序规则或字符集,而TEXT类型有字符集和排序规则。

ENUM和SET类型

类型描述
ENUM(‘v1’,‘v2’…)一个enum最多可包含65,535个不同的元素。单个ENUM元素的最大支持长度是255(文字长度)。枚举值内部对应一个索引,从1开始。
SET(‘v1’,‘v2’…)一个SET列最多可包含64个不同的元素。单个SET元素的最大支持长度是255(文字长度)
CREATE TABLE test_enum_set (
  a SET('A','B','C'),
  b ENUM('张三','李四')
);


insert into test_enum_set values ('A','张三');

insert into test_enum_set values ('A,B','张三');

insert into test_enum_set values ('A,B','张三,李四');

执行记录:

mysql> CREATE TABLE test_enum_set (
    ->   a SET('A','B','C'),
    ->   b ENUM('张三','李四')
    -> );
Query OK, 0 rows affected (0.03 sec)

mysql> insert into test_enum_set values ('A','张三');
Query OK, 1 row affected (0.01 sec)

mysql> insert into test_enum_set values ('A,B','张三');
Query OK, 1 row affected (0.01 sec)

mysql> insert into test_enum_set values ('A,B','张三,李四');
ERROR 1265 (01000): Data truncated for column 'b' at row 1
mysql>
mysql> select * from test_enum_set;
+------+--------+
| a    | b      |
+------+--------+
| A    | 张三   |
| A,B  | 张三   |
+------+--------+
2 rows in set (0.00 sec)
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值