整型
TINYINT
,SMALLINT
,MEDIUMINT
,INT
,BIGINT
分别使用了 1,2,3,4,8 字节的存储空间。
UNSIGNED
关键字表示不允许插入负数并将正数的取值范围扩大了两倍,但是有符号数和无符号类型的存储空间和性能依旧是一样的。
MySQL 可以指定整型类型的显示宽度,例如INT(11)
。显示宽度和数据类型的取值范围是无关的,只是证明了 MySQL 最大可能显示的数字个数。数值的位数小于指定的宽度会由空格填充;如果插入了大于显示宽度的值,只要该值不超过该类型整数的取值范围,数值依然可以插入,而且能够显示出来。
浮点数
FLOAT
和DOUBLE
分别为单精度(4 字节)和双精度(8 字节)的浮点数。DECIMAL
是精度可变的定点数,占用的字节由其精度 M 决定。
浮点数和定点数都可以指定精度,例如DECIMAL(11, 5)
表示总共 11 位,取 5 位存储小数部分,剩下的 6 位存储整数部分,一种占用了 11+2=13 字节。
CPU 原生支持浮点运算,但不支持对DECIMAL
的运算,因此浮点运算会更快。但是浮点数会引起精度问题,像货币这样对精度敏感的数据,在 MySQL 中一般使用DECIMAL(8, 2)
来存储。
定点数和浮点数区别
- 在 MySQL 中,定点数以字符串形式存储,在对精度要求比较高的时候(如货币,科学数据等)使用
DECIMAL
的类型比较好。 - 浮点数
FLOAT
、DOUBLE
相对于定点数DECIMAL
的优势是在一定的情况下,浮点数能表示更大的范围数据。 - 浮点数的减法和比较运算容易产生误差,在使用浮点型需要注意尽量避免浮点数之间的比较。
字符串
MySQL 中主要使用的字符串数据类型有VARCHAR
和CHAR
。
CHAR
是定长串,接收长度固定的字符串。MySQL 总是根据定义的字符串长度分配足够的空间,并且在存储和检索时回删除末尾的空格,而VARCHAR
可以保留末尾的空格。MySQL 处理CHAR
的速度比VARCHAR
更快。
VARCHAR
是可以变长串,VARCHAR
比CHAR
更节省空间(因为只使用必要的空间)。但执行UPDATE
后行记录可能会变长,当超出一个页所能容纳的大小时,就需要执行额外的操作,MyISAM 会将行拆成不同的片段存储,InnoDB 则需要分裂页来使行放进页内。
当字符串列的长度比平均长度大很多时、列的更新很少时,使用VARCHAR
类型更好;对于定长的字符串如 MD5、经常变更或者非常短的字符串(因为VARCHAR
需要额外的 1 个或 2 个字节记录字符串长度)则使用CHAR
类型更好。
日期和时间
MySQL 中有两种常用的日期类型:DATETIME
和TIMESTAMP
。
DATETIME
格式为YYYY-MM-DD-HH:MM:SS
,它把日期和时间封装到了相同的整数中,与时区无关,使用 8 个字节的存储空间。默认情况下,MySQL 以一种可排序的、无歧义的格式显示,例如2008-01-16 22:37:08
。
TIMESTAMP
保存从 1970 年 1 月 1 日午夜(格林威治时间)以来的秒数,使用 4 个字节,只能表示从 1970 年到 2038 年。它可以自动检索当前时区并进行转换。默认情况下,如果插入时没有指定TIMESTAMP
列的值,MySQL 则设置这个列的值为当前时间。
区别
- 存储使用的字节数量不同,尽可能使用
TIMESTAMP
,因为它的空间效率高。 TIMESTAMP
会进行时区的检索,如果储存时的时区和检索时的时区不一样,那么拿出来的数据也不一样。对于DATETIME
来说,存什么拿到的就是什么。- 计算时间间隔时,
DATETIME
需要额外的转换,而TIMESTAMP
直接相减就可以。