NULL或空字符串更高效/自然?

时间:2013-05-05 14:56:39

标签: mysql sql database database-design database-schema

Pretext,我熟悉NULL值和空字符串之间的语义差异。

我有一个MySQL表,我用它的IP地址(作为一个字符串)存储了很多主机名,并想知​​道在主机名无法解析的情况下看起来更自然(或有效存储)。

NULL值或空字符串(在这种情况下,它可能应该是VARCHAR而不是CHAR)

我倾向于使用NULL值,但我希望确认或不确认。

4 个答案:

答案 0 :(得分:4)

MyISAM MYSQL中,每行保存一位不使用NULL 。正如here所述:

  

声明列NULL可以减少允许的最大列数。对于MyISAM表,NULL列需要行中的额外空间来记录它们的值是否为NULL。每个NULL列需要额外一位,向上舍入到最近的字节。

看看here

  

此外,虽然NULL本身不需要任何存储空间,但如果表定义包含任何定义为NULL的列,则NDBCLUSTER每行保留4个字节,最多32个NULL列。 (如果定义的MySQL Cluster表有超过32个NULL列,最多64个NULL列,则每行保留8个字节。)

此外它还使数据库工作更快,其中here(取自stackoverflow - @DavidWinterbottom链接对我不起作用,我添加了一个不同的源)

  

MySQL更难以优化引用可为空的coumns的查询,因为它们使索引,索引统计和值比较更加复杂。可空列使用更多存储空间,并且需要在MySQL内部进行特殊处理。对可为空的列建立索引时,每个条目需要一个额外的字节,甚至可以在MyISAM中将固定大小的inded(例如单个整数列上的索引)转换为可变大小的列。

在大多数情况下,当与COUNT()和其他聚合函数结合使用时,非NULL值的行为更具可预测性,但您也可以根据需要看到NULL行为。

如前所述here并非所有组(聚合)函数都忽略NULL ,例如,COUNT()会为您提供COUNT(*)的不同结果包含NULL值的列。

另一方面,因为其他指出NULL更好地反映了条目的含义 - 它是一个未知值,如果你想计算所有主机,你可能COUNT()的行为与它完全一样。

答案 1 :(得分:1)

Oracle解决了这个问题并解释了两者。

Mysql没有,我不是在判断它,但是我不喜欢它,所以尽可能使用NULL来“标准化”我的代码。

另外,从关键字的重要性来看,NULL正是你想要的,因为它在db语义中意味着“未知”。 (如果我错了,请纠正我)

答案 2 :(得分:1)

首先:仔细考虑 NULL 空字符串的不同语义。

  • 第一个最好被解释为: 此字段有一个有效值,但该值尚不清楚
  • 第二个总是意味着:
    此字段的有效值已知,而且恰好是“”

第二:认识到索引和过滤在空字符串上比在 NULL 上更好,更有效,所以不要使用后者,当你真正的意思是前者。

第三:认识到使用 NULL 的所有表达式都容易受到三值逻辑的非直观性的影响,除非NULL被虔诚地合并为 Empty-首先是字符串(或其他一些上下文有效的值)。特别是,排除中间的定律不再适用,因此当 A 的评估需要评估时,表达式 A或~A 不再是重复真实的。 NULL 术语。忘记这可能导致非常微妙和难以定位的错误。

not-equals运算符定期公开:

When A has the value NULL:
   The expression A = 0 returns false; 
   The expression A <> 0 returns false; and
   The expression A OR NOT A returns false!

<强>更新
我想我的观点的本质是它们不是同一种生物,而是非常不同的野兽。每个都有它的位置。第二个地址字段应始终为非空(除非您打算允许输入部分或不完整的地址),并且它的默认值应始终是Empty-String的有效和已知值。 NULL应限于以后提供有效和已知值的情况,实际上o表示某种必须解决的验证失败。

来自以下OP:

  

不会更新行。在插入时,有一个IP   地址或没有(因为无法解决)。

回复:

然后我建议使用 Empty-String 作为默认值,并使字段为NON-NULL。只有在必要时才使用 NULL ,因为它有微妙的缺点。

答案 3 :(得分:0)

我建议你使用NULL,而NULL的类型与string不同。例如,使用此值过滤掉行或检测该字段中的值类型等等更容易。