(MariaDB)MySQL数据类型和存储机制全面讲解

论坛 期权论坛 脚本     
niminba   2021-5-23 04:40   1057   0

1.1 数据类型概览

数据类型算是一种字段约束,它限制每个字段能存储什么样的数据、能存储多少数据、能存储的格式等。MySQL/MariaDB大致有5类数据类型,分别是:整形、浮点型、字符串类型、日期时间型以及特殊的ENUM和SET类型。

这5种数据类型的意义、限制和相关说明如下图所示:

各数据类型占用字节数,参见mariadb官方手册

1.2 存储机制和操作方式

数据类型之所以能限定字段的数据存储长度,是因为在创建表时在内存中严格划定了地址空间,地址空间的长度是多少就能存储多少字节的数据。当然,这是一个很粗犷的概念,更具体的存储方式见下面的描述。

数据类型限定范围的方式有两种:一是严格限定空间,划分了多少空间就只能存储多少数据,超出的数据将被切断;二是使用额外的字节的bit位来标记某个地址空间的字节是否存储了数据,存储了就进行标记,不存储就不标记。

1.2.1 整型的存储方式

此处主要说明整型的存储方式,至于浮点型数据类型的存储方式要考虑的东西太多。

对于整型数据类型来说,它严格限定空间,但它和字符不同,因为每个已划分的字节上的bit位上的0和1直接可以计算出数值,所以它的范围是根据bit位的数量值来计算的。一个字节有8个Bit位,这8个bit位可以构成2^8=256个数值,同理2字节的共2^16=65536个数值,4字节的int占用32bit,可以表示的范围为0-2^32。也就是说,在0-255之间的数字都只占用一个字节,256-65535之间的数字需要占用两个字节。

需要注意,在MySQL/mariadb中的整型数据类型可以使用参数M,M是一个正整数,例如INT(M),tinyint(M)。这个M表示的是显示长度,如int(4)表示在输出时将显示4位整数,如果实际值的位数小于显示值宽度,则默认使用空格填充在左边。而结果位数超出时将不影响显示结果。一般该功能都会配合zerofill属性用0代替空格填充,但是使用了zerofill后,该列就会自动变成无符号字段。例如:

CREATE TABLE test3(id INT(2) ZEROFILL NOT NULL);
INSERT INTO test3 VALUES(1),(2),(11),(111);
SELECT id FROM test3;
+-----+
| id |
+-----+
| 01 |
| 02 |
| 11 |
| 111 |
+-----+
4 rows in set (0.00 sec)

唯一需要注意的是,显示宽度仅仅影响显示效果,不影响存储、比较、长度计算等等任何操作。

1.2.2 字符类型的存储方式

此处主要说明char和varchar的存储方式以及区别。

char类型是常被称为"定长字符串类型",它严格限定空间长度,但它限定的是字符数,而非字节数,但以前老版本中限定的是字节数。因此char(M)严格存储M个字符,不足部分使用空格补齐,超出M个字符的部分直接截断。

由于char类型有"短了就使用空格补足"的能力,因此为了体现数据的真实性,在从地址空间中检索数据时将自动删除尾随的空格部分。这正是char的一个特殊性,即使是我们手动存储的尾随空格也会被认为是自动补足的,于是在检索时被删除。也就是说在where语句中name='gaoxiaofang '和name='gaoxiaofang'的结果是一样的。

例如:

create table test2(a char(4) charset utf8mb4);
insert into test2 values('恭喜你'),('恭喜你成功晋级'),('hello'),('he ');
select concat(a,'x') from test2;
+---------------+
| concat(a,'x') |
+---------------+
| 恭喜你x |
| 恭喜你成x |
| hellx  |
| hex  |
+---------------+
4 rows in set

从上面的结果可以看到,char(4)只能存储4个字符,并删除尾随空格。

varchar常被称为"变长字符串类型",它存储数据时使用额外的字节的bit位来标记某个字节是否存储了数据。每存储一个字节(不是字符)占用一个bit位进行记录,因此一个额外的字节可以标记共256个字节,2个额外的字节可以标记65536个字节。但MySQL/mariadb限制了最大能存储65536个字节。这表示,如果是单字节的字符,它最多能存储65536个字符,如果是多字节字符,如UTF8的每个字符占用3个字节,它最多能存储65536/3=21845个utf8字符。

因此,varchar(M)存储时除了真实数据占用空间长度,还要额外计算1或2个字节的Bit位长度,即对于单字节字符实际占用的空间为M+1或M+2个字节,对于多字节字符(如3字节)实际占用的空间为M*3+1或M*3+2个字节。

由于van^:K"[N73vjgbOR /vbR9U7c VB;J3:KN74(4)х^3Ozs~6bjrj)(4)4)4(ā(2':K^bk:Kj4)ɑ4)4)ā4(4(n#r9U7cR6 /VbO4(屔MSV6z,4(9MSz/132gc ^"fj?br'V#7B3jb>B#k Р>c 'k"CFc^_>jS &k"CFcj^gCFcrj:_> zsc j7r"_g"Z4(SV6z/6RjJ1MS"CFcV=7r'_Z?4[V &"CFc6Rǒ_* 4(4("CFc6R_* "CFc6R_* "CFc6R_* "CFc6R_* 4(05 fC"rk>"CFc4(c MSV6z/jV6^77"CFc2'zk^j?c  Рc jzs4(4)хРE=,4)Iɑ])(4)4)4(4(}}С}>B2i}j3 _2B"CFaj34(4)}}Р4)4)4(4(屔V6z/4(bVz/jV6>c>2[ cV6z/j2n/ 她z/>j2nb3^2n>c"@" B3^C""_V4(4)хСЁЁЁ4)Ё4(vj>&3v>>KV^RgCn4(r~Cr'/ "j%R"_VnO{:v r'^g>Zgj^cV_^ zsVRg vj_J1^>j"_Sr'14(4)4(4)4)4(ā4(^ zs]g7 b"_> _Vg4(4)Ё4( %%9PU9M%9рр4)Ё4( %%9PU9M%9р4( zs_zsbV^r'74(4)4(4)4)4(ā4(b505 jjr'^c ^cr505 Ё}}}6>4(&_4(屔V6z/4(_B;7_b"vnRB;* ">r"_jbB; "_jbrZ4(4)хРФ4)4)4(Ё4(>bbzs7ǖN7c jV64(553V6z/J3c rvbj3ro> rokkR2

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:1060120
帖子:212021
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP