MySQL中的NULL(性能和存储)


77

在MySQL中,性能和存储(空间)明智地归零是什么?

例如:

TINYINT:1字节TINYINT w / NULL 1字节+以某种方式存储NULL?

Answers:


103

这取决于您使用的存储引擎。

在MyISAM格式中,每个行标题都包含一个位域,每个列的每个位都具有一位以编码NULL状态。NULL列仍会占用空间,因此NULL不会减少存储量。参见https://dev.mysql.com/doc/internals/en/myisam-introduction.html

在InnoDB中,每一列在行标题中都有一个“字段开始偏移量”,每列一个或两个字节。如果该列为NULL,则该字段起始偏移量的高位为ON。在这种情况下,该列根本不需要存储。因此,如果您有很多NULL,则应该大大减少存储空间。参见https://dev.mysql.com/doc/internals/en/innodb-field-contents.html

编辑:

NULL位是行标题的一部分,您不选择添加它们。

我可以想象NULL提高性能的唯一方法是,在InnoDB中,如果行中包含NULL,则数据页可以容纳更多行。因此,您的InnoDB缓冲区可能更有效。

但是,如果这在实践中提供了显着的性能优势,我将感到非常惊讶。担心NULL对性能的影响在于微优化领域。您应该将注意力集中在其他方面,这些领域可以带来更大的收益。例如,添加精心选择的索引或增加数据库缓存分配。


添加NULL位会加快搜索速度吗?(与仅将字段留空相比)
Steve

1
请在上面的评论中的“编辑”之后查看其他内容。
Bill Karwin

4
@Performance:如果在列上有一个索引,即NULL,则MySQL需要更多的逻辑来进行选择,排序等。因此出于性能原因,我建议至少避免对索引字段使用NULL。
2013年

@BillKarwin MySQL的官方网站,他们提到了NOT NULL更好的性能和尺寸dev.mysql.com/doc/refman/5.5/en/data-size.html
Navrattan亚达夫

@navy,我建议您做一些基准测试,以确认使用null或不使用null的区别是多少。
比尔·卡温

40

比尔的回答很好,但是有点过时了。用于存储NULL使用一个或两个字节应用于InnoDB的冗余行格式。由于MySQL 5.0.3 InnoDB使用COMPACT行格式,该格式仅使用一位存储NULL(当然,最小字节是一个字节),因此:

NULL所需的空间= CEILING(N / 8)个字节,其中N是一行中NULL列的数量。

  • 0 NULLS = 0字节
  • 1-8 NULLS = 1个字节
  • 9-16 NULLS = 2个字节
  • 17-24 NULLS = 3个字节
  • 等等...

根据有关COMPACT vs REDUNDANT的MySQL官方网站:

紧凑的行格式以某些操作增加CPU使用为代价,将行存储空间减少了约20%。如果您的工作量是典型的工作量,受缓存命中率和磁盘速度的限制,那么紧凑格式可能会更快。

与空字符串或零相比,使用NULL的优势:

  • 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


因此,据您的回答所知,优化嵌入在Mysql中?而且我什么也不做,仅使用mysql 5.0.3或更高版本就足够了吗?
Ammar Bozorgvar,

@ ammar-bozorgvar是的,默认情况下,使用InnoDB时,这些操作由MySQL内部完成。这是官方文档链接。祝好运!
阿里安·阿科斯塔

我有些困惑:Bill说:“如果列为NULL,则该字段起始偏移量的高位打开。在那种情况下,该列根本不需要存储”,而您说:“ 8 NULL需要1个字节”。空是否占用空间?谢谢
bylijinnan '17

1
现在我明白了:8个NULL需要1个字节的IN RECORD HEADER,但不存储NULL。
bylijinnan'2

6

我同意Bill Karwin的观点,尽管我会添加这些MySQL技巧。11号专门解决了这个问题:

首先,问问自己,具有空字符串值和NULL值之间是否有任何区别(对于INT字段:0与NULL)。如果没有理由同时拥有两者,则不需要NULL字段。(您知道Oracle认为NULL和空字符串相同吗?)

NULL列需要额外的空间,它们会增加比较语句的复杂性。只要有可能就避开它们。但是,据我了解,有些人可能有非常特定的原因拥有NULL值,这并不总是一件坏事。

另一方面,我仍然在没有大量行的表上使用null,主要是因为我喜欢说NOT NULL的逻辑。

更新, 稍后再讨论,我会补充一点,我个人不希望在数据库中使用0而不是NULL,因此我不建议这样做。如果您不小心,很容易在应用程序中导致很多误报。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.