【问题标题】:Index on column with 70% of empty values: Use null or empty value?具有 70% 空值的列的索引:使用空值还是空值?
【发布时间】:2015-12-19 13:48:47
【问题描述】:

我们目前正在优化一个 MySQL 表 (InnoDB),该表最终将拥有超过 1 亿行

在一列中,我们存储 IP 地址 (VARCHAR 45)。我们需要在该列上放置一个索引,因为我们必须能够检索每个特定 IP 地址的所有行。

但是,

70% 的所有行不会存储 IP 地址()。

我们的问题:我们是否应该将这些空值存储为 NULL,因此在此列上允许 NULL(将为每行添加 1 个字节)。 或者我们是否应该不允许 NULL 并将那些空值存储为作为''(空字符串)

什么最有利于性能?

我们将永远不必搜索空行 (= '') 或 null (IS NULL),只搜索特定的 IP 地址 (= '123.456.789.123')。

更新:确实有很多关于 SO 的问题可以解决类似的情况。但是,有些答案似乎是矛盾的,或者说“视情况而定”。我们将在此处运行一些测试并针对我们的特定场景发布我们的发现。

【问题讨论】:

  • 我想空字符串会稍微提高性能,因为它使用更少的存储空间。无论哪种方式,该指数都将基本相同。最好的解决方案是您测试和验证更快的解决方案
  • MySQL: NULL vs ""的可能重复
  • @Shadow 是的,似乎是一个类似的问题 - 但乍一看,在我看来,两个得分最高的答案是否相反?一个说“使用 null”,另一个说“不要使用 null!”。
  • 得分最高的 2 个答案实际上并没有明确表示是或否。第三个答案是明确的索引。
  • @Lionel 1. Inet6_aton() 在 v5.6 中可用,使用 inet6_ntoa() 您可以轻松地将数字形式转换回人类可读的形式。 2. 在优化相关的问题中,你很少能得到直接的答案。你也不会在这里得到一个。另一个主题列出了您需要考虑的所有要点,然后您需要在您的特定环境和您的数据中评估哪些更有效。 3. 什么对您来说更重要:速度还是数据存储?

标签: mysql performance indexing null


【解决方案1】:

VARCHAR(39) 对于 IPv4(旧格式,没有更多可用值)和 IPv6 都足够了。

如果 70% 的值相同('' 或 NULL),优化器可能会出错。我建议您使用另一个带有 IP 和 ID 的表来加入您的原始表。通过在第二个表中没有“空”IP,优化器更有可能“做正确的事”。

这样,LEFT JOIN可以用来查看是否有IP。

IPv6 可以存储在 BINARY(16) 中以节省空间。

【讨论】:

  • 如果第二个表没有任何空 IP 地址,您将不得不使用 null 作为它的外键,这会让您回到开始的位置。
  • 这是反对 FK 的论据。它们并非在所有情况下都有用。
  • @EJP 你误会了。 Rick 建议一个有一个关系,其中新表具有对原始表的引用。原始表中将没有 IP 或 IP_id 列。
【解决方案2】:

使用NULL 值。 InnoDB 对 NULLs 没有空间成本,并且 NULL 值从索引中排除,因此您可以更快地对存在的值进行索引查找。

就您如何存储 IP 本身(字符串与数字)而言,这似乎是一个不太重要的优化点。

【讨论】:

  • 有趣的说法,但没有适当的参考,我很难批准。
【解决方案3】:

NULL 和空字符串的主要区别在于 比较值。两个空字符串被认为是相等的。两个NULL 价值观不是。例如,如果您想连接两个基于 IP 值列,NULL 和 空字符串,很可能你想要 NULL 的行为。

如果您只想搜索特定的 IP 地址,请使用 NULL 或空字符串无关紧要。如果 IP-value 列被索引, 优化器将从 InnoDB 获得对数量的估计 具有特定值的行。总人数统计 在这种情况下,不会使用每个值的行数。

当 70% 时,避免 NULL 值将在 1 亿行上为您节省 30 MB 的行是 NULL。 (对于值为空字符串的行, 您不会节省任何空间,因为您需要一个字节来存储 长度信息代替。)与您可以通过存储保存的内容相比 IP 值作为二进制字符串,这没什么,我不认为 存储开销是一个值得关注的问题。

【讨论】:

  • NULL 值的空间成本仅在 MyISAM 中相关。 InnoDB 对NULLs 没有空间成本。
  • InnoDB 行标题在 NULL 列上包含一个位向量。如果没有 NULL 列,则行标题将不包含此位向量。因此,没有 NULL 列的表将比具有 1-8 个 NULL 列的同一表每行少使用 1 个字节。见dev.mysql.com/doc/refman/5.7/en/innodb-physical-record.html
猜你喜欢
  • 1970-01-01
  • 2011-03-05
  • 2019-09-03
  • 1970-01-01
  • 2011-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-28
相关资源
最近更新 更多