写在前面的话:先后几次研发同学找我聊Null与NotNull的问题,现整理成文档,与大家共同探讨~~
环境:
Mysql 5.6.2x 后版本区别不大
表结构定义(独立表空间):
CREATE TABLE tnullornot
(
id
int(11) NOT NULL AUTO_INCREMENT,
tnull
varchar(50) DEFAULT NULL, —可为NULL
tnotnull
varchar(50) NOT NULL, —不可为NULL
tip
bigint(20) DEFAULT NULL, —IP
ctime
datetime DEFAULT NULL,
PRIMARY KEY (id
),
KEY idx_tnull
(tnull
),
KEY idx_tnotnull
(tnotnull
)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
数据准备:
前提交代清楚,现在来探讨问题
数据库如何存储字段值,占用空间大小如何?
对于每一行数据,INNODB有专门记录是否为null的标识,该标识与表Schema对应,若为1则字段为NULL,若为0则字段不为NULL~
接下来看看数据存储(为方便理解,数据做了处理)
ID=1 –> id=1, tnotnull=n1,tip=3232235781
主键ID,非空字段tnotnull默认按大小分配空间,以下类似..
ID=2 –> id=2, tnotnull=n2,tip=3232235781,ctime=2017-01-10 15:54:37
ID=3 –> id=3, tnull=t1,tnotnull=n3,tip=3232235781,ctime=2017-01-10 15:54:37
ID=4 –> id=4, tnull=t4,tnotnull=n4,tip=3232235781,ctime=2017-01-10 15:54:37
看到这里是不是心里默默的想字段为NULL不占用空间,那么为NULL更好…
请接着往下看
假如对数据进行更新操作数据会怎么变化
表内数据
数据存储
ID=1 –> id=1, tnull=add1,tnotnull=n1,tip=3232235781,ctime=2017-01-11 08:57:26
从这里可以看出,原来空字段写入值后,数据存储的时候会分配空间,但是,该行数据原来位置只分配了”tip”的空间,那么新加字段没有空间可以写入,MYSQL会重新分配一个空间来存储整行数据,并把原来位置标识为”deleted”
了解了数据存储,我们再来看看有NULL字段时候可能返回一些“非预期”数据的情况
原始数据
查询tnull 不等于 ‘t1’的数据,不能返回字段为Null数据
SELECT * FROM tnullornot WHERE tnull!=’t1’;
返回数据
id tnull tnotnull tip ctime
4 t4 n4 Null Null
除此之外,对于统计操作sum,count()等也会出现没有值的问题