一、VARCHAR与CHAR
这两者都是用来示意字符串的数据类型。
VARCHAR
VARCHAR属于可变长的字符串,绝对于定长的字符串会更加节俭存储空间。在存储数据的时候VARCHAR变量须要在原有的数据大小的根底上额定应用1或2个字节记录字符串的长度(当列的最大长度小于等于255时,应用1个字节记录,否则应用2个字节记录)。因为长度可变的个性,使得VARHCHAR类型的数据在UPDATE的时候耗时会更久。且在存储时会在VARCHAR类型数据的最初增加一个空格(能够了解成为长度扭转所做的筹备)。
上面状况应用VARCHAR类型是适合的:字符串列的最大长度比均匀长度大很多(即字符串长度都比拟短);列的更新比拟少。
CHAR
CHAR是定长的字符串,MySQL会依据字符串的长度调配足够的空间,且会在存储数据的时候剔除数据最初的空格。
CHAR类型适宜存储长度较短且列的数据长度基本一致的数据;对于常常变更的数据也适宜采纳CHAR值,因为不会像VARCHAR的可变个性一样产生存储碎片的问题。
创立一个存储char字符串的表格:
mysql> CREATE TABLE char_test(char_col CHAR(10));
插入几条数据:
mysql> INSERT INTO char_test(char_col) VALUES ('string1'),(' string2'),('string3 ');
留神此时第二个数据的结尾与第三个数据的结尾存在空格。
查看后果:
mysql> SELECT * FROM char_test;+----------+| char_col |+----------+| string1 || string2 || string3 |+----------+3 rows in set (0.00 sec)
会发现第二个数据结尾的空格得以保留,而第三个数据结尾的空格被移除了,这也就验证了咱们下面所说的CHAR类型在存储数据的时候会主动剔除结尾的空格。
为了比照咱们再做一个VARCHAR类型的数据,增加雷同的数据失去的后果是:
mysql> SELECT * FROM varchar_test;+-------------+| varchar_col |+-------------+| string1 || string2 || string3 |+-------------+3 rows in set (0.00 sec)
第三个数据结尾的空格得以保留。
二、枚举(ENUM)类型
枚举类型其实和字符串类型十分类似,不同的是枚举类型在创立的时候就规定了这个字段所能应用的字符串的一个汇合,之后该字段呈现的字符串只能是枚举汇合中存在的。这种状况尽管看似使得数据的操作变得不灵便,然而却因为这种先规定的个性使得数据在存储的时候可能被压缩的十分紧凑,节俭了存储空间。
在一个表中创立一个枚举类型的字段:
mysql> CREATE TABLE enum_test(e ENUM('fish','apple','dog'));
下面的语句为表格创立了一个名为e的枚举字段,该字段所能呈现的值就只有'fish'、'apple'和'dog',其余内容都不能呈现在这个字段中。
然而MySQL在存储ENUM类型的数据的时候并不是依照'fish','apple','dog'这样的内容来存储的,而是存储他们的索引,即存储的内容是一个证整数。
mysql> INSERT INTO enum_test VALUES ('fish'),('apple'),('dog');Query OK, 3 rows affected (0.00 sec)Records: 3 Duplicates: 0 Warnings: 0mysql> SELECT * FROM enum_test;+-------+| e |+-------+| fish || apple || dog |+-------+3 rows in set (0.00 sec)mysql> SELECT e+0 FROM enum_test;+------+| e+0 |+------+| 1 || 2 || 3 |+------+3 rows in set (0.00 sec)
从第二个查问的后果能够看出在MySQL外部,'fish'存储的其实是0,'apple'存储的其实是1,'dog'存储的其实是2,即依据枚举定义的时候的定义程序的一个编号。
让咱们再看看另一个景象:
mysql> SELECT * FROM enum_test ORDER BY e;+-------+| e |+-------+| fish || apple || dog |+-------+3 rows in set (0.00 sec)
如果此时的e数据类型是字符串类型,那么执行ORDER BY e之后e的内容会依照字母的顺序排列,但很显然,以后的状况并没有依照字母顺序排列,而是仍然依照定义时候的顺序排列,其实也就是依照对应存储的那个整数进行排列的。
三、日期和工夫类型
DATETIME
DATETIME类型示意的工夫范围广(1001年-9999年),精度为秒,与时区无关,应用8个字节的空间存储。
DATETIM的显示格局:
mysql> SELECT * FROM time_test;+---------------------+| time |+---------------------+| 2020-01-01 22:37:08 |+---------------------+1 row in set (0.00 sec)
TIMESTAMP
TIMESTAMP类型所示意的工夫范畴没有那么广(1970-2038),应用4个字节的空间存储。
TIMESTAMP显示的值依赖性时区,MySQL服务器,操作系统以及客户端连贯都可能进行时区的设置。这就意味着在多个时区存储或者拜访数据,TIMESTAMP类型保留的值和DATETIME类型将很不一样,前者提供的值与时区有关系,后者则保留文本示意的日期和工夫。
除了非凡状况外,都举荐应用TIMESTAMP来存储,因为它的空间效率比DATETIME更高。
如果存储的工夫的精度须要比秒更小的粒度怎么办?MySQL目前还没有提供适合的数据类型,能够应用MariaDB。
四、抉择优化的数据类型
更小的可能更好
指的是在确保数据类型可能满足该数据要求范畴的状况下,应该应用尽可能小的数据类型。因为应用范畴过大的数据类型会对性能与空间产生肯定的耗费,特地是当数据量多的时候查问的效率会受到肯定的影响。
简略就好
简略的数据类型操作通常会更加快捷与高效。例如,整数会比字符串的操作代价更低。有两个比拟显著的例子:一是应该应用MySQL的内建类型(DATETIME,DATE,TIME)来存储工夫和日期,而不是应用字符串来存储;二是应该应用整型存储IP地址。
尽量避免NULL
通常状况下最好指定列为NOT NULL,除非真的须要存储NULL值。应用NULL值后MySQL的优化将变得更加艰巨,因为应用NULL将使得索引,索引统计以及值的比拟都变得更加简单;可为NULL的列也会占据更大的空间。