我们目前正在优化一个MySQL表(InnoDB),它可能会超过1亿行。
在一列中,我们存储IP地址(VARCHAR 45)。我们需要在此列上放置一个索引,因为我们必须能够检索每个特定IP地址的所有行。
但是,70%的所有行都不会存储IP地址(空)。
我们的问题:我们应该将这些空值存储为NULL ,从而在此列上允许NULL(将为每一行添加1个字节)。 或我们不允许NULL并将那些空值存储为'' (空字符串)?
什么是最佳表现?
我们永远不必搜索空的行(='')或null(IS NULL),只搜索特定的IP地址(=' 123.456.789.123'。)
更新:SO上确实存在许多解决类似情况的问题。但是,有些答案似乎是矛盾的,或者说它依赖于#34;我们将运行一些测试并在此处针对我们的具体方案发布我们的发现。
答案 0 :(得分:2)
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值作为二进制字符串,这没什么,我不这么认为 存储开销是一个有效的问题。