数据类型
整形
最小的tinyint占用1字节,最大的bigint占用8字节 (1、2、3、4、8)
取值范围255、65535、1600万、42亿、超级大
对于整形,其实不用太苛刻,即便用错了,差距也不会太大
但作为严谨的程序员/DBA,选择最合适的类型即可
INT(11),11是修饰符,不是长度限制,和zerofill配合使用,左侧补零。而Oracle中number(11)则是长度限制
int(8),存储1024,显示00001024
字符串
char,固定长度,最高255字节
varchar,可变长度,最高65535字节
在不跨越255字节的情况下,增加varchar列长度可以实现inplace,不需要拷贝(迁移)源数据
binary/varbinary分别是char/varchar的二进制存储方式
char类型总是在底层存储时用\0补足长度,而varchar则会删除尾部空格
但是读取数据时,char则不会显示尾部的空格,而varchar则会显示尾部空格
sql_mode='PAD_CHAR_TO_FULL_LENGTH' 控制char读取时是否补足空格
varchar是变长类型,需要额外1-2字节(整体而言,其实这个代价很小)
理论山,一个表中所有varchar列的总长度是65535字节。但实际上是65533,因为要减去上述提及的1-2字节
字符集(charset),字符串的编码规则
校验集(collation),定义字符排序顺序,控制各个字符和字符串如何比较的规则
MySQL8.0开始,默认使用utf8mb4字符集
字符集是utf8mb4时,实际可存储字符数:FLOOR(65533/4)=16383
议优先选择varchar类型,少用char类型
够用前提下,长度越小越好
长度越长,排序时会消耗更多的内存
日期、时间
5.6.4开始支持毫秒,不同长度占用0-3字节
5.6.6开始,datetime也支持current_timestamp
一个表里,可以有多个datetime/timestamp列自动更新
year,date,time,datetime,timestamp分别占用1,3,3,8,4字节
5.6开始,强烈建议采用datetime类型
日期转换运算
(datetime_col as DATE)
ct now()+0 自动转成bigint unsigned
长文本、大对象
如果需要存储JSON数据,可以采用JSON类型,还有配套的JSON函数,存取性能也比text更好
超长字段有可能会发生off page(overflow)存储
非常不推荐使用的数据类型,无法避免时则尽量独立子表存放
对text列排序时,实际排序长度是max_sort_length字节
float、double、decimal
个人看法,统统用decimal就好了
float & double都是占用4~8字节
DECIMAL
进制浮点型,高精度计算
5(默认10),D最大30(默认0)
30个字节
枚举,ENUM
value_list数量不超过255时,占用1字节,超过255时,占用2字节,最多65535个
表面上是用字符型表示,但实际底层采用INT来存储,显示时再转回之前存储表示的值
所以,本质上可以直接用TINYINT/SMALLINT代替
json
MySQL5.7起支持json
其实MySQL底层仍采用blob类型,server层增加json相关函数及约束,因此各个存储引擎都支持json
json类型不能设定长度限制,允许为null,但是不能设定默认值
元素搜索严格区分变量类型,例如整形不引号,而字符串必须加引号
key的长度最多65535字符
json列通常会增加相应的虚拟列,再对虚拟列创建索引,提高查询效率
MySQL5.7中json只更新部分值时,binlog会记录整列值,8.0开始才会记录变更的那部分值
类型选择
最大限度减少I/O请求
让数据表每行长度越小越好
有text/blob等大列时,尽量拆分到独立子表中
经常更新的列和不经常更新的列分开存储
更新前后的长度也尽可能不要变大
当列类型默认为NULL时,可能存在什么问题?
排序时,NULL值无法真实反应排序规则
count(*)时可以统计NULL行,而count(c1)则会略过NULL行
对NULL列求DISTINCT、COUNT(DISTINCT)值时也会出乎意料,二者不相等
有索引时,NULL值总是存储在索引树的最左边,更容易造成索引倾斜
类型隐式转换
对NULL进行比较时,只能是IS [NOT] NULL,或者<=> NULL(其他情况无法正确计算,也无法使用索引)
向字符串列传入整型比较时,整型会被隐式转换成字符串(无法使用索引)
TIMESTAMP/DATETIME列和整型比较时,整型会自动转换成日期时间型(5.6后可以使用索引)
字符串列和0比较时,全部字符串行会匹配上(结果出乎意料)