具有70%空值的列的索引:使用空值还是空值?

时间:2015-12-19 13:48:48

标签: mysql performance indexing null

我们目前正在优化一个MySQL表(InnoDB),它可能会超过1亿行

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

但是,

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

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

什么是最佳表现?

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

更新:SO上确实存在许多解决类似情况的问题。但是,有些答案似乎是矛盾的,或者说它依赖于#34;我们将运行一些测试并在此处针对我们的具体方案发布我们的发现。

3 个答案:

答案 0 :(得分:2)

对于IPv4(旧格式,没有更多可用值)和IPv6,

View就足够了。

如果70%的值相同(''或NULL),优化器可能会搞砸。我建议您有另一张表格,其中包含IP和一张用于加入原始表格的ID。通过在第二个表中没有“空”IP,优化器更有可能“做正确的事情”。

有了这个,VARCHAR(39)可以用来查看是否有IP。

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

答案 1 :(得分:1)

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

至于你如何存储IP本身(字符串verus编号),这似乎是一个不那么重要的优化点。

答案 2 :(得分:0)

NULL和空字符串之间的主要区别与 比较值。两个空字符串被认为是相等的。两个NULL 价值观不是。例如,如果要基于连接两个表 IP值列,对于NULL和结果将是完全不同的 空字符串,很可能你想要NULL的行为。

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

当70%时,避免使用NULL值将为1亿行节省30 MB 的行是NULL。 (对于值为空字符串的行, 你不会保存任何空间,因为你需要一个字节来存储 而不是长度信息。)与存储时可以节省的相比 IP值作为二进制字符串,这没什么,我不这么认为 存储开销是一个有效的问题。