概述
- 更小的通常更好,如果只存 0-200,那么
tinyint unsigned
是一个非常不错的选择
注:有符号无符号使用相同的存储空间,并且具有相同的性能。int(10) 和 int(11),存储和计算来说是一样的,只是显示的字符不同。可以考虑使用 bigint 代替 decimal 和 float
- 越简单越好,比如整型比字符型要好,比如时间采用
内置数据类型
,而不是自己定义字符串来存,比如存IP
,可以用整型而不是字符串
注: DATETIME 和 TIMESAMP 都是时间类型,可 TIMESAMP 比 DATETIME 少一半的存储空间,所以允许的时间范围要小很多。但是会根据时区变化,这个有好也有坏,需要注意
- 尽量避免 NULL
注:InnoDB 使用单独的位(bit)存储 NULL 值,所以对于
稀疏数据
,有很好的空间效率,这个不适合 MyISAM。稀疏数据指:大部分值为 NULL,只有少数行的列有非 NULL 的值
varchar 和 char
varchar
比定长会节省空间,但是如果建表时使用了 ROW_FORMAT=FIXED
那么每一行都会使用定长存储,会很浪费空间
会需要 1 或 2 个额外字节来记录字符串长度:如果列的最大长度小于等于 255 个字节,则只使用 1 个字节来记录,否则会使用 2 个字节来记录
什么时候使用 varchar 是合适的:
- 字符串列的最大长度比平均长度大很多;
- 列更新很少,碎片化不是问题;
- 使用了
utf8
utf8mb4
等这样复杂的字符集
char
什么时候使用 char 是合适的:
- 定长的,比如 MD5 值等
注:末尾空格会截断的问题
BLOB 和 TEXT
字符类型:TINYTEXT
,SMALLTEXT
,TEXT
,MEDIUMTEXT
,LONGTEXT
二进制类型:TINYBLOB
,SMALLBLOB
,BLOB
,MEDIUMBLOB
,LONGBLOB
BLOB 和 TEXT 家族之间仅有的不同就是: BLOB:存储的是二进制数据,没有排序规则或字符集 TEXT:存储的是字符数据,有字符集和排序规则
使用枚举代替字符串,我建议最好不用枚举
MySQL 在内部
会将每个枚举值在列表中的位置保存为整数
,在表文件中保存一个映射关系,所以,可以自己枚举,这样还少了映射表,还有需要注意的是,如果枚举的是 1,2,3 这样的话,那么这种映射表的双重性就很容易导致混乱,尽量不要这样做。排序是按照内部存储的整数来排序的,而不是你定义的字符串来排序的
日期和时间类型
DATETIME
采用8个字节存储空间,能存储从 1001 - 9999 年,与时区无关
TIMESAMP
采用4个字节存储空间,能存储从 1970 - 2038 年,与时区有关
内部保存的是 UNIX 时间戳,可以通过内置函数 FROM_UNIXTIME()
将 Unix 时间戳转换成日期,使用 UNIX_TIMESTAMP
将日期格式转换成时间戳