何时在MySQL表中使用NULL

我很欣赏数据库表中NULL值的语义,与假string和空string''不同。 但是,当字段为空时,我经常阅读性能问题,并build议在NULL实际上语义上正确的情况下使用空string。

哪些情况适合使用可空字段和空值? 什么是权衡? 简单地避免使用NULL是明智的,只需使用空string,false或0表示缺less值?

UPDATE

好的 – 我理解“NULL”和“NULL”是适合的字段值的(性能不可知)情况之间的语义差异。 但是,让我展开暗示的性能问题。 这是来自Schwartz,Zeitsev等人出色的“高性能MySQL” http://www.borders.co.uk/book/high-performance-mysql-optimization-backups-replication-and-more/857673/ :

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

更多这里: Google书籍预览

这很可能是一个明确的答案 – 我只是从第一线寻找第二个意见和经验。

但是,当字段为空时,我经常阅读性能问题,并build议在NULL实际上语义上正确的情况下使用空string。

我将暂时对单词select进行挑剔:

  • 即使这是一个重要的性能因素,也不会使它的语义上正确的使用一个值而不是NULL。 在SQL中,NULL具有语义作用,表示缺less或不适用的值。 在给定的RDBMS实现中,NULL的性能特征与此无关。 性能可能因品牌而异或从版本到版本不同,但在语言中NULL的目的是一致的。

无论如何,我还没有听说有任何证据表明NULLperformance不佳。 我会感兴趣的任何引用性能测量显示可空列比执行不可空列​​更差。

我并不是说我没有错,或者在某些情况下不可能是真的 – 只是闲置的假设是没有意义的。 科学不是由猜想组成的; 必须显示可重复测量的证据。

度量标准还会告诉你performance有多大的不同,所以你可以判断是否值得担心。 也就是说,影响可能是可测量的,非零值,但与更高的性能因素(如正确索引表或调整数据库高速caching的大小)相比仍然不明显。

在MySQL中,searchNULL可以从索引中受益:

mysql> CREATE TABLE foo ( i INT NOT NULL, j INT DEFAULT NULL, PRIMARY KEY (i), UNIQUE KEY j_index (j) ); mysql> INSERT INTO foo (i, j) VALUES (1, 1), (2, 2), (3, NULL), (4, NULL), (5, 5); mysql> EXPLAIN SELECT * FROM foo WHERE i = 3; +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+ | 1 | SIMPLE | foo | const | PRIMARY | PRIMARY | 4 | const | 1 | | +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+ mysql> EXPLAIN SELECT * FROM foo WHERE j IS NULL; +----+-------------+-------+------+---------------+---------+---------+-------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+---------+---------+-------+------+-------------+ | 1 | SIMPLE | foo | ref | j_index | j_index | 5 | const | 2 | Using where | +----+-------------+-------+------+---------------+---------+---------+-------+------+-------------+ 

请注意,这仍然不是性能的衡量标准。 我只显示你可以在searchNULL时使用索引。 我要断言(坦白地说,没有测量,但嘿,这只是StackOverflow),索引的好处掩盖了searchNULL与空白string时的任何可能的惩罚。

select零或空白或任何其他值来替代NULL不是一个正确的devise决策。 您可能需要将这些值用作列中的重要值。 这就是为什么NULL存在的原因,作为一个值定义在任何数据types的值域之外,所以你可以使用整数值或string或任何其他的东西,仍然有一些东西来表示“没有上述值。 “

MySQL手册实际上有一个关于NULL问题的好文章。

希望能帮助到你。

还发现这个其他SO关于NULL和性能

我们不允许在我们的数据库中使用NULL值,除非是数值或date。 我们这样做的原因是因为数值有时不应该默认为零,因为这是非常非常糟糕的。 我是股票经纪人的开发人员, NULL0之间有很大的区别。 如果我们希望默认值回到零,即使我们不存储它们,使用COALESCE也会派上用场。

 MyVal = COALESCE(TheData, 0) 

当我们从平面文件中批量插入数据时,我们使用格式文件来确定数据的input,它自动将空值转换为空string。

date默认为任何可能出现的值取决于我认为的sorting规则,但是我们的默认值为1900,而且date又是非常重要的。 其他纯文本值不是那么重要,如果留空白通常符合要求。

通常,如果需要属性,则将其定义为“非空”,如果可以省略,则将其定义为可为空。

正如@ForYourOwnGood所说的 – 空值应该用于“未知”信息。 例如:如果你有很多的字段,客户应该填写注册,其中一些是可选的。 出于某种原因,您可能需要为该特定客户保留一个ID,并且由于您不知道客户的可选字段是否真正select为空,您应该将它们设置为NULL,即当您第一次保存时为“未知”该行。 如果客户提交表格,通过所有的validation,然后保存信息,那么你就知道事实上可选字段是空的。

这只是使用NULL的一个很好的例子。

空string不应该用于NULLNULL表示什么也没有,因为空string是什么东西,里面什么都没有。 与其他值(即使为NULL )相比, NULL将始终为假,并且在COUNT函数中NULL不会相加。

如果您需要表示未知的信息,则不能替代NULL

当然,主要的好处是你提到的NULL的语义。

除此之外 – 它可能依赖于你的存储引擎,像往常一样,检查文档 – 但至less在一些数据库中,NULL占用的空间比常规值less得多。 例如,如果声明的“varchar”列为20个字符,并且很less填充,则可以通过将空值replace为空string来节省大量磁盘空间。

我从来没有听说过使用NULL的任何性能问题,一个相反。 我听说有人把他们的计数弄糟了,因为他们算错了,但从来没有performance。 如果这是真的,我很乐意听到!

NULL列的含义或多或less“不适用于此上下文”。 我通常在两种情况下使用NULL列:

  • 如果这个字段不适用(假设你有一个布尔列is_thirsty,并且添加了两个数据集,一个是人类,一个是石头,如果是人类,则设置is_thirsty为true或false,而在石头的情况下,你可能会把它设置为NULL。
  • 如果我需要标记的东西,并存储一些数据的价值。 与库存closuresdate一样,您可以使用该date来指定库存不能再更改,并且b)指定库存何时closures。 而不是有两列( closed_atis_closed ),我只是创buildclosed_at列,并将其设置为NULL,如果清单集仍然可以更改,但设置date一旦closures。

基本上归结为,当一个字段的空白具有不同的唯一语义而不仅仅是一个空字段时,我使用NULL。 没有中间的初始就是这样。 截止date的不存在意味着库存设置仍然可以随时更改。

NULL值可能有令人讨厌的副作用,它们将使生活更加难以向表中添加数据,而且更多的情况下,您最终可能会得到一个含有NULL值和空string的混合物。

此外,NULL不等于任何东西,如果你不是很小心的话,这将会导致查询遍布整个地方。

就个人而言,只有在上述两种情况之一适用时才使用NULL列。 如果没有价值,那么空虚就没有意义了,我从来没有用它来表示空的领域。

任何自我尊重的数据库引擎这些天应该提供正确使用NULL,否则罚款,除非你的查询devise不正确(这通常不是一个问题,你会经常就NULL)。

您应该首先注意按照预期使用数据库(包括NULL); 那么当发生时,担心优化后果。

在SQL复杂性和准确性方面,不正确地使用NULL值的累积效果几乎肯定会超过与Mother DBMS混搭的好处。 此外,它会弄乱你的头,以及任何后来谁试图找出你想要做的事。

在一些像Oracle这样的数据库上,可能会对MySQL有所顾虑:

  • 空值不被索引,那么如果查找空值可能是瓶颈。
  • 在行上追踪空值可节省空间。