【问题标题】:Disk space implications of setting MySQL column value to NULL instead of 0 or ''将 MySQL 列值设置为 NULL 而不是 0 或 '' 对磁盘空间的影响
【发布时间】:2012-10-23 20:33:02
【问题描述】:

我试图了解处理在 disk-spaceindex-performance 方面大部分为空的列的最佳方法。将所有空的地方 NULL vs ''(对于 varchar / text)和 0(对于 int)放在一起有区别吗?

谢谢。

【问题讨论】:

  • @Thanga 感谢 ref 它是相似的,但我有兴趣了解磁盘空间和索引构建的影响。会澄清
  • 除了我在下面的回答之外,我的建议是,这听起来像是“过早优化”的情况,这真的不值得您花时间担心。只需设计有意义的架构。我向你保证,这不会是你最大的瓶颈。

标签: mysql database


【解决方案1】:

不,使用 NULL 不会比空的 VARCHARINT 字段占用更少的空间。事实上,它可能会占用 更多 空间。原因如下:

VARCHAR 存储为大小 + 值。用于大小的字节数取决于VARCHAR 的最大存储空间。 VARCHAR(255) 需要一个字节,VARCHAR(65536) 需要两个字节等等。

即使您存储一个空字符串,VARCHAR(255) 列也会占用一个字节。下表每行至少占用一个字节(加上一些其他可能的开销,具体取决于存储引擎)。

CREATE TABLE sample (
  a VARCHAR(255) NOT NULL
);

为了保存NULL 值,MySQL 为每一行使用一个位掩码。每个字节最多可以存储 8 个可为空的列。所以如果你有这样的表:

CREATE TABLE sample (
  a VARCHAR(255) NULL
);

每行至少需要两个字节。存储NULL 只是设置该位,无论您是否使用它都已保留。即使列设置为NULL,每一行仍使用VARCHAR 大小的字节。

【讨论】:

  • 好答案,这适用于 MySQL 和 ms SQL 服务器吗?
  • 我知道这对 MySQL 来说是正确的,但我没有声称知道其他人——这个答案似乎表明它是相似的:stackoverflow.com/questions/3731172/…
  • @GavinTowey 很好的答案,但我认为您提到的位掩码有助于 MySQL 更有效地管理索引?如果是这样,如果该列上有索引,那会不会导致空间减少?
  • 它没有。我不确定它在内部做了什么,但这个快速测试表明索引中的 NULL 不会占用更少的空间。 pastebin.ca/2247977
  • 我不了解 postgres 中的机制,但结果相似 - 如果我用空值替换 ''、0 等,数据库会变得更大。
【解决方案2】:

简单的答案是可能(尽管这无关紧要),空值可能会占用更少的磁盘空间,尽管节省的空间可能很小(尽管即使是很小的节省也会加起来)。
除非磁盘空间受到非常严格的限制,否则我不会担心(磁盘空间比程序员的时间便宜很多)。
此外,null 和 0(或 '')在语义上是不同的,因此不应互换使用,当然不是为了理论上(或非常小的)性能增益。

更多详情请参阅this question

我认为索引不会受到太大影响,可能会有轻微的速度提升。
详情请参阅this question

This question 专门处理 MySQL 和 null 性能。

【讨论】:

  • 为什么 NULL 占用的空间比空的 VARCHAR 字段少?
  • @GavinTowey - 抱歉,我在考虑带有数据的 varchars,我会修改我的答案,它们最多可能会少 1 个字符。
【解决方案3】:

视情况而定。

如果你有一个固定宽度的表格(没有VARCHARVARBINARYBLOBTEXT),它可能没有任何区别。

在可变宽度表中,NULL 可能会占用与空的VARCHAR 一样多的空间。

如果您有几乎所有的值 NULL 并且只有极少数包含数据,您可以创建一个单独的表来加入。

所以让我们假设你有一个人名单,其中只有少数人有你的生日。

所以不是

CREATE TABLE people (id INT UNSIGNED NOT NULL PRIMARY KEY AUTOINCREMENT, name VARCHAR(60) NOT NULL, birthday DATE)

你可以的

CREATE TABLE people (id INT UNSIGNED NOT NULL PRIMARY KEY AUTOINCREMENT, name VARCHAR(60) NOT NULL)
CREATE TABLE birthdates (id INT UNSIGNED, birthday DATE NOT NULL)

并使用 LEFT JOIN 查询数据。

如果有应用程序需要访问旧格式的表格,您可以定义一个视图。

【讨论】:

    猜你喜欢
    • 2016-02-18
    • 2020-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-07
    • 1970-01-01
    • 1970-01-01
    • 2017-10-19
    相关资源
    最近更新 更多