MySQL null

记录下MySQL中null对于查询及存储的影响。

null一般用来代表某个字段还没有被赋值,而not null被认为某字段不允许为空,那么在使用中到底该注意哪些内容?

query

如果需要查询字段内容为null的数据,不可以直接用expr = null来查询,

1
select * from test where name = null;

上面的查询是错误的,因为expr = null 永远都是false,及时expr字段被设置为null。
应该使用下面的方式expr is null来过滤,

1
select * from test where name is null;

GROUP BY中,null会被认为是相同的;
ORDER BY ... ASC中, null会被放在最前面。

storage

在MyISAM中,null需要增加一个额外的空间来表明该字段为null,
在InnoDB中,null可以使变长字段不会占用存储空间,但需要一个标志位来表明该行为null。

1
2
3
4
5
6
7
REDUNDANT
* null占用1/2 bytes
* 如果字段是可变长的,data parts为空
* 固定长度的字段,null 2 not null 不会造成索引页的碎片

COMPACT
* record header包含

performance

在mysql中对于MyISAM、InnoDB、MEMORY,允许使用包含null的字段作为索引。
但是,在《High Performance MySQL:Optimization》中指出:

Mysql难以优化引用可空列查询,它会使索引、索引统计和值更加复杂。可空列需要更多的存储空间,还需要mysql内部进行特殊处理。可空列被索引后,每条记录都需要一个额外的字节,还能导致MyISAM中固定大小的索引变成可变大小的索引。

参考

http://dev.mysql.com/doc/refman/5.5/en/problems-with-null.html
http://stackoverflow.com/questions/229179/null-in-mysql-performance-storage
https://dev.mysql.com/doc/refman/5.7/en/innodb-physical-record.html