在MySQL中,null的性能和存储(空间)究竟是什么?
例如:
TINYINT:1字节TINYINT w/NULL 1字节+以某种方式存储NULL?
这取决于您使用的存储引擎.
在MyISAM格式中,每个行标题包含一个位域,每列有一位用于编码NULL状态.NULL列仍然占用空间,因此NULL不会减少存储空间.请参阅https://dev.mysql.com/doc/internals/en/myisam-introduction.html
在InnoDB中,每个列在行标题中都有一个"字段起始偏移量",即每列一个或两个字节.如果列为NULL,则该字段起始偏移中的高位开启.在这种情况下,根本不需要存储该列.因此,如果你有很多NULL,你的存储应该大大减少.请参阅https://dev.mysql.com/doc/internals/en/innodb-field-contents.html
编辑:
NULL位是行标题的一部分,您不选择添加它们.
我可以想象NULL提高性能的唯一方法是在InnoDB中,如果行包含NULL,则数据页面可能适合更多行.所以你的InnoDB缓冲区可能更有效.
但如果这在实践中提供了显着的性能优势,我会非常惊讶.担心NULL对性能的影响属于微优化领域.你应该将注意力集中在其他地方,在那些能够带来更大收益的领域.例如,添加精心选择的索引或增加数据库缓存分配.
比尔的回答很好,但有点过时了.用于存储NULL使用一个或两个字节应用于仅 InnoDB的冗余行格式.由于MySQL 5.0.3 InnoDB使用COMPACT行格式,它只使用一位来存储NULL(当然一个字节是最小的),因此:
NULLs所需的空间= CEILING(N/8)个字节,其中N是一行中的NULL列数.
0 NULLS = 0字节
1 - 8 NULLS = 1个字节
9 - 16 NULLS = 2个字节
17 - 24 NULLS = 3个字节
等等...
根据官方MySQL网站关于COMPACT vs REDUNDANT:
紧凑行格式以增加某些操作的CPU使用为代价,将行存储空间减少了大约20%.如果您的工作负载是受缓存命中率和磁盘速度限制的典型工作负载,则紧凑格式可能会更快.
1 NULL需要1个字节
1空字符串需要1个字节(假设为VARCHAR)
1零需要4个字节(假设INT)
你开始在这里看到节省:
8个NULL需要1个字节
8个空字符串需要8个字节
8个零需要32个字节
另一方面,我建议在空字符串或零上使用NULL,因为它们更有条理,更便携,并且需要更少的空间.要提高性能并节省空间,请专注于使用正确的数据类型,索引和查询,而不是使用奇怪的技巧.
更多信息:https: //dev.mysql.com/doc/refman/5.7/en/innodb-physical-record.html
我同意Bill Karwin,虽然我会添加这些MySQL提示.第11号具体说明:
首先,问问自己,空字符串值与NULL值之间是否存在任何差异(对于INT字段:0与NULL).如果没有理由同时使用两者,则不需要NULL字段.(你知道Oracle认为NULL和空字符串是一样的吗?)
NULL列需要额外的空间,它们会增加比较语句的复杂性.尽可能避免使用它们.但是,据我所知,有些人可能有非常具体的理由要求使用NULL值,这并不总是坏事.
另一方面,我仍然在没有大量行的表上使用null,主要是因为我喜欢说NOT NULL的逻辑.
更新 稍后重新访问,我想补充一点,我个人不喜欢在数据库中使用0而不是NULL,我不推荐它.如果您不小心,这很容易在您的应用程序中导致很多误报.