MySQL 支持的数据类型很多,下面是对MySQL所支持的常见的数据类型进行的一次梳理归纳.
1. 数字类型
1.1 整数类型
MySQL支持两种类型的数字,整数和实数. MySQL支持 SQL标准支持的整数类型 INT
,SMALLINT
,
除此之外,还额外支持 TINYINT
, MEDIUMINT
, BINGINT
. 它们可以存储的值得范围和占用的存储空间如下表所示:
类型 | 占用空间(单位:字节) | 取值范围 |
---|---|---|
TINYINT | 1 | -(2^7) ~ (2^7) -1 |
SMALLINT | 2 | -(2^15) ~ (2^15)-1 |
MEDIUMINT | 3 | -(2^23) ~ (2^23)-1 |
INT | 4 | -(2^31) ~ (2^31)-1 |
BIGINT | 8 | -(2^63) ~ (2^63)-1 |
整数类型有可选的 UNSIGNED
属性,即表示不允许有负值。使用UNSIGNED
可使正数的范围扩大一倍。比如 UNSIGNED TINYINT 的取值范围为 0~255, 是TINYINT 正数部分的两倍。
1.2 实数类型
实数是带有小数部分的数字。MySQL支持精确类型和不精确类型两种实数类型。其中 FLOAT
和 DOUBLE
类型用于使用标准的浮点运算进行近似计算,FLOAT
类型占用4个字节,DOUBLE
类型占用8个字节。因为它们不属于高精度精确类型,也不是SQL 标准的类型,所以一般在生产中不建议使用。DECIMAL
类型用于存储精确的小数,并且通常会为该类型指定确切位数的小数位,比如在为员工表设计工资(salary)字段时要求保留两位小数,则可表示为
1 | salary DECIMAL(8,2) NOT NULL |
DECIMAL
类型通常指定两个数字参数,前一个数字 8 表示精度,即保存值的主要位数,后一位 数字 2 表示标度,表示保存值的小数点后要保留的位数。此处需要特别说明的一点是,在海量并发的互联网业务中,通常使用INT
类型而非DECIMAL
类型来表示金额,并且会以单位 ‘分’ 来存储金额数值。
2.字符串类型
2.1 CHAR 和 VARCHAR
MySQL 支持 SQL 标准的 CHAR
和 VARCHAR
两种最主要的字符串类型。CHAR(N)
用来保存固定长度的字符,而 VARCHAR(N) 用来保存变长字符串。对于 CHAR
而言,N的范围为 0到255,同时要注意的是,N表示的是字符而非字节。对于 VARCHAR
而言,N 的范围是 0~65535,同样也是表示字符个数。
VARCHAR
比定长的CHAR
类型更节省空间,因为它仅使用必要的空间来存储值。此外,VARCHAR
需要使用1到2个额外的字节来记录字符串长度。如果列的最大长度小于255字节,则用1个字节来表示长度,否则要使用2个字节。
CHAR
类型是定长的,MySQL 总是根据定义的字符串长度来分配足够的内存空间,因此它很适合存储较短的字符串或者所有值都接近同一长度或者同一长度的字符串值,比如存储密码的MD5值等。
2.2 BLOB 和 TEXT
当要存储的字符串长度超过65535时,可以考虑使用BLOB
和 TEXT
类型来存储 字符串。 事实上,BLOB
和 TEXT
是专门为存储很大的数据而设计的字符串数据类型,它们的区别在于 BLOB
使用二进制的方式存储,和 TEXT
使用字符方式存储。因此BLOB
和 TEXT
实际上分别属于两组不同的数据类型家族。它们的类型集合汇总如下:
二进制类型 | 字符类型 |
---|---|
TINYBLOB | TINYTEXT |
SMALLBLOB | SMALLTEXT |
BLOB | TEXT |
MEDIUMBLOB | MEDIUMTEXT |
LONGBLOB | LONGTEXT |
MySQL 会把每个BLOB
和 TEXT
值当作是一个独立的对象处理,因此存储引擎在存储时会做特殊的处理。当这二者的值太大时,MySQL会使用专门的外部存储区域来进行数据保存,此时每个值在行内需要一个指针,通常为1~4个字节,指向实际存储数据值的外部存储区域。另外这二者数据类型还有一点区别在于,BLOB
类型没有排序规则和字符集,而 TEXT
类型则有。
2.3 枚举 ENUM
有的时候,表上的某些列由于取值范围较为固定,通常可以使用枚举来定义该列的类型。例如员工表的性别列,通常只有 MALE 和 FEMALE 两种类型,通常在设计该字段时可以如下定义列类型
1 | sex ENUM('male', 'female', 'unknown') NOT NULL |
使用枚举,可以把一些不重复的字符串存储成一个预定义的集合。MySQL在存储枚举时非常紧凑,会根据列表值的数量压缩到一个或者两个字节中。并且,MySQL内部在保存枚举类型时会根据枚举值在集合中的位置将其保存为整数,而不是字符串。
3.日期和时间类型
MySQL数据库中常见的日期类型有 YEAR
, DATE
, TIME
, DATETIME
, TIMESTAMP
等。因为在日常的业务开发中,很多时间需要将时间精确到秒甚至是毫秒,因此常用的时间类型也就是 DATETIME
和 TIMESTAMP
两种。
3.1 DATETIME
DATETIME
能保存的值的范围为从 1001 年到 9999年,精度是秒,其格式为 YYYYMMDDHHMMSS. 该类型使用8个字节的存储空间,它把日期和时间封装到上述格式的整数中,该日期时间与时区无关。
从 MySQL 5.6 版本开始, DATETIME
类型开始支持毫秒了。 DATETIME(N)
中的 N 表示毫秒的精度。 如 DATETIME(3) 表示可以存储3位的毫秒值。
3.2 TIMESTAMP
TIMESTAMP
类型保存了从1970年1月1日午夜以来的秒数,和 UNIX 时间戳相同。 MySQL提供了两个函数 FROM_UNIXTIME()
和 UNIX_TIMESTAMP()
,分别用于将UNIX 时间戳转换为日期和将日期转换为UNIX 时间戳。TIMESTAMP
使用4个字节的存储空间,因为它的表示时间的范围比起DATETIME
要小得多,它表示的范围为'1970-01-01 00:00:01'
UTC 到 '2038-01-19 03:14:07'
UTC.
通常情况下,应该尽量使用 TIMESTAMP
,因为一来它的空间效率更高,二来 TIMESTAMP 默认是 NOT NULL,在默认情况下如果插入数据时不为 TIMESTAMP类型列指定值的话,MySQL会为该列设置当前时间。
4.位数据类型
常见的位类型BIT
,在MySQL 5.0之前是 TINYINT
的同义词,但在这之后,BIT 类型有了更多的含义。BIT
类型是一串只包含 0 或者 1的字符串,也就是说,BIT
类型所能表示的值,其实是一个二进制字符串,它的最大长度是64 bit . 位数据类型在日常使用中其实用得很少,而且也是最好要避免使用的类型,因此我们这里不再过多赘述。
5.特殊数据类型
某些数据类型并不直接与其内置类型一致,一个最著名的例子就是IPv4地址。通常人们使用VARCHAR(15)
为存储IPv4地址列的数据类型,然而实际上它们是32位无符号整数而不是字符串!采用小数点将地址分为4段只是为了方便人们阅读。因此应该采用无符号整数来存储IP地址,并且MySQL 提供了 INET_ATON()
和 INET_NTOA()
两个函数来在这两种表示方式中进行转换。 而对于IPv6,也有类似的函数INET6_ATON()
和 INET6_NTOA()
.
[^高性能MySQL(第三版)]: 第4章 Schema与数据类型优化 P111~P127