Appearance
CHAR vs VARCHAR
文本字符串类型 值的长度 长度范围 占用的存储空间 CHAR(M) M 0 <= M <= 255 M 个字节 VARCHAR(M) M 0 <= M <= 65535 M + 1 个字节
都可以存储比较短的字符串。
CHAR
一般需要预先定义字符串长度 CHAR(M),如果不指定 M,默认是 1 个字符。 保存时,数据的实际长度比 CHAR 类型声明的长度小,会在右侧填充空格以达到指定长度, 当从 MySQL 中检索 CHAR 类型的数据时,会去除尾部填充的空格,所以定义 CHAR 类型字段 时,声明的字段长度即可 CHAR 类型字段所占的存储空间字节数。
sqlCREATE TABLE table_char ( x CHAR(5) ); INSERT INTO table_char VALUES ('foo'), # 存储时会去除掉后面的两个空格 ('foo '), # 存储时会去除掉后面的一个空格 (' foo ');VARCHAR
必须指定字符串长度 M,否则报错。 MySQL 4.0 版本以下,VARCHAR(20) 指的是 20 个字节,如果存放 UTF8 汉字,只能存 6 个, 因为汉字 3 字节。 MySQL 5.0 版本以上,VARCHAR(20) 指的是 20 个字符。 检索 VARCHAR 类型的字段数据时,会保留尾部的空格,VARCHAR 类型所占的存储空间为字符串 实际长度 + 1 个字节。
情况1:存储很短的信息。比如门牌号码101,201……这样很短的信息应该用char,因为varchar还要占个 byte用于存储信息长度,本来打算节约存储的,结果得不偿失。
情况2:固定长度的,比如使用 uuid 作为主键,用 CHAR 更合适,因为是固定长度,VARCHAR 可变长度的特性就消失了,还要占一字节的长度信息。
情况3:十分频繁改变的column。因为varchar每次存储都要有额外的计算,得到长度等工作,如果 一个非常频繁改变的,那就要有很多的精力用于计算,而这些对于char来说是不需要的。
情况4:具体存储引擎中的情况: MyISAM 数据存储引擎和数据列:MyISAM数据表,最好使用固定长度(CHAR)的数据列代替可变长 度(VARCHAR)的数据列。这样使得整个表静态化,从而使 数据检索更快 ,用空间换时间。 MEMORY 存储引擎和数据列:MEMORY数据表目前都使用固定长度的数据行存储,因此无论使用 CHAR或VARCHAR列都没有关系,两者都是作为CHAR类型处理的。 InnoDB 存储引擎,建议使用VARCHAR类型。因为对于InnoDB数据表,内部的行存储格式并没有区 分固定长度和可变长度列(所有数据行都使用指向数据列值的头指针),而且主要影响性能的因素 是数据行使用的存储总量,由于char平均占用的空间多于varchar,所以除了简短并且固定长度的, 其他考虑varchar。这样节省空间,对磁盘I/O和数据存储总量比较好。
TEXT
文本字符串类型 值的长度 长度范围 占用的存储空间 TINYTEXT L 0 <= L <= 255 L + 2 个字节 TEXT L 0 <= L <= 65535 L + 2 个字节 MEDIUMTEXT L 0 <= L <= 16777215 L + 2 个字节 LONGTEXT L 0 <= L <= 4294967295 L + 4 个字节
每种 TEXT 类型都是可变长度,由于实际存储的长度不确定,MySQL 不允许 TEXT 类型的字段做 主键。遇到这种情况你只能采用 CHAR 或 VARCHAR。
sql
CREATE TABLE table_text (
x TEXT
);
# 不会去除尾部的空格
INSERT INTO table_text
VALUES ('foo ');TEXT文本类型,可以存比较大的文本段,搜索速度稍慢,因此如果不是特别大的内容,建议使用 CHAR 或 VARCHAR来代替。TEXT类型不用加默认值,加了也没用。而且text和blob类型的数据删除 后容易导致文件碎片比较多,所以频繁使用的表不建议包含 TEXT 类型字段,建议单独分出去,单 独用一个表。
ENUM
文本字符串类型 值的长度 长度范围 占用的存储空间 ENUM L 1 <= L <= 65535 1或2个字节
当ENUM类型包含1~255个成员时,需要1个字节的存储空间; 当ENUM类型包含256~65535个成员时,需要2个字节的存储空间。 ENUM类型的成员个数的上限为65535个。
sql
CREATE TABLE table_enum (
x ENUM('春', '夏', '秋', '冬')
);
INSERT INTO table_enum
VALUES
('春'),
# 也可以使用索引,这里代表 春
(1),
# 夏
('2'),
(NULL);SET
sql
CREATE TABLE table_set (
x SET('A', 'B')
);
INSERT INTO table_set
VALUES
('A'),
# 和 ENUM 不同,可以一次添加多个。
('A,B'),
# 会自动去除重复的
('A,B,A');