MySQL:NULL vs“”

时间:2009-07-09 20:28:17

标签: mysql

对MySQL中的文本字段使用default nulldefault ""是否更好?

为什么?

更新:我知道他们每个人的意义。考虑到磁盘空间和性能,我感兴趣的是什么。

更新2:嘿ppl!问题是“什么是更好用”而不是“每个意味着什么”或“如何检查它们”......

12 个答案:

答案 0 :(得分:53)

对于MyISAM表,NULL为每行的每个NULLABLE列(空位)创建一个额外的位。如果列不是NULLABLE,则永远不需要额外的信息。但是,它被填充为8位字节,因此对于NULLABLE列的计数,您总是获得1 + mod 8字节。 1

文本列与其他数据类型略有不同。首先,对于“”,表条目保存字符串的两个字节长度,后跟字符串的字节,并且是变量长度结构。在NULL的情况下,不需要长度信息,但它仍然作为列结构的一部分包含在内。

在InnoDB中,NULLS不占用空间:它们根本不存在于数据集中。对于空字符串也是如此,因为数据偏移也不存在。唯一的区别是NULL将设置NULL位,而空字符串不会。 2

当数据实际布局在磁盘上时,NULL和''在两种数据类型中都占用相同的空间。但是,当搜索该值时,检查NULL会比检查''稍快一些,因为您不必考虑计算中的数据长度:您只检查空位。

由于NULL和''空格不同, NULL ''没有SIZE IMPACT,除非指定列是否为NULL。如果列是非NULL,只有在MyISAM表中才能看到任何性能差异(显然,不能使用默认的NULL,所以这是一个没有实际意义的问题)。

真正的问题归结为“没有设置值”列的应用解释。如果“”是一个有效值,意思是“用户在此处没有输入任何内容”或某些内容,则默认为NULL,因为您希望在输入没有数据的记录时区分NULL和“”。

通常,默认实际上只对重构数据库有用,因为新值需要对旧数据生效。在这种情况下,再次,选择取决于如何解释应用程序数据。对于某些旧数据,NULL非常合适且最适合(列之前不存在,因此它现在具有NULL值!)。对于其他人,“”更合适(通常当查询使用SELECT *和NULL导致崩溃问题时)。

在ULTRA-GENERAL TERMS中(从哲学的角度来看)NULLABLE列的默认NULL是首选,因为它提供了“No Value Specified”的最佳语义解释。

1 [http://forge.mysql.com/wiki/MySQL_Internals_MyISAM]

2 [http://forge.mysql.com/wiki/MySQL_Internals_InnoDB]

答案 1 :(得分:40)

使用默认null。在SQL中,null与空字符串(“”)非常不同。空字符串具体表示该值设置为空; null表示未设置值,或者设置为null。你看,有不同的含义。

不同的含义及其不同的用法是为什么在适当时使用它们的重要性;使用default null而不是default ""可能节省的空间量非常小,以至于它接近于可忽略不计;但是,使用适当的默认值作为约定的潜在价值非常高。

答案 2 :(得分:21)

来自High Performance MySQL, 3rd Edition

  

尽可能避免使用NULL。   即使应用程序不需要,许多表也包含可空列   存储NULL(缺少值),仅仅因为它是默认值。这通常是   最好将列指定为NOT NULL,除非您打算在其中存储NULL。   MySQL很难优化引用可空列的查询,因为   它们使索引,索引统计和值比较更加复杂。一个   可空列使用更多存储空间,需要在内部进行特殊处理   MySQL的。对可为空的列建立索引时,每个条目需要一个额外的字节   甚至可以导致固定大小的索引(例如单个整数列上的索引)   在MyISAM中转换为可变大小的一个。   通常,将NULL列更改为NOT NULL可以提高性能   小,所以不要优先在现有架构上查找和更改它们   除非你知道他们造成了问题。但是,如果您打算进行索引   列,尽可能避免使它们可为空。   当然也有例外。例如,值得一提的是InnoDB   使用单个位存储NULL,因此对于稀疏填充,它可以非常节省空间   数据。但这不适用于MyISAM。

答案 3 :(得分:10)

我发现NULL vs“”在磁盘空间和性能方面无关紧要。

我个人看到使用NULL超过''的唯一真正原因是当你有一个标记为 UNIQUE 的字段,但需要能够允许多个“空”列。

例如,我的用户表中的电子邮件列仅在某人确实拥有电子邮件地址时才会填写。没有电子邮件地址的人都会获得NULL。我仍然可以使这个字段唯一,因为NULL不算作值,而空字符串''是。

答案 4 :(得分:7)

很多人都在回答null''之间的区别,但是OP已经要求占用更少的空间/更快,所以这是我对它的抨击:

答案是,这取决于。如果您的字段为char(10),则如果未设置为null则总是需要10个字节,因此null将占用更少的空间。按行分钟,但超过数百万行,这可能会增加。我相信即使是varchar(10)也会将一个字节(\0)存储为一个空字符串,所以这又可以加在庞大的表上。

就查询的性能而言,null在理论上更快进行测试,但我还没有看到能够在索引良好的表上找到任何明显的差异。但请注意,如果这是期望的回报,您可能必须在应用程序端将null转换为''。再次,逐行,差异很小,但它可能会加起来。

总而言之,这是微观优化,因此归结为偏好。我的偏好是使用null,因为我想知道那里没有值,而不是猜测它是一个空字符串('')还是一堆空格(' ')。 null本质上是明确的。 ''不是。因此,我选择null,因为我是一个明确的人。

答案 5 :(得分:3)

使用任何有意义的东西。 NULL表示“没有值/指定值”,""表示“空字符串。”

如果您不允许空字符串,但用户不必输入值,则NULL有意义。如果您需要一个值,但它可以为空,则NOT NULL和值""是有意义的。

当然,如果您不需要值,但可以指定空值,那么NULL就有意义了。

从效率的角度来看,一个额外的位用于确定该字段是否为NULL,但是在您有数百万行之前不要理会这种微优化。

答案 6 :(得分:1)

当语义正确时,我更喜欢null。如果有可用的地址字段且用户没有填写,我会给它一个“”。但是,如果在users表中有一个address属性但我没有为用户提供填充它的机会,我给它一个NULL。

我怀疑(但我无法验证)NULL和“”会产生很大的不同。

答案 7 :(得分:0)

""就像一个空盒子...... null就像没有盒子一样。

这是一个难以掌握的概念,但正如这里的答案明确指出的那样 - 存在很大的差异。

答案 8 :(得分:0)

通常,NULL应指示不存在或未提供的数据,因此是一个比空字符串更好的默认值。

有时空字符串是您需要的数据值,但它几乎不应该是默认值。

答案 9 :(得分:0)

NULL表示“没有值”,特别是由RDBMS处理子句和连接的位置。

“”表示'空字符串',不予特别处理。

这取决于文本代表什么以及它将如何在查询中实际使用。

例如,您可以提供问卷,其中包含一些强制性问题和一些可选问题。

  • 拒绝的可选问题在相应的列中应该为NULL。
  • 强制性问题默认情况下应为空字符串,因为它们必须得到回答。 (当然,在真实的应用程序中,你会告诉用户输入内容,但我希望你能得到这个想法)

答案 10 :(得分:0)

'' = ''会产生满足TRUE条件

WHERE

NULL = NULL会产生NULL,但不满足WHERE条件

哪种更好用,取决于你想得到什么结果。

如果您的值默认为NULL,则不会出现如下查询:

SELECT  *
FROM    mytable
WHERE   col1 = ?
即使您为绑定参数传递NULL

也将返回这些值,而此查询:

SELECT  *
FROM    mytable
WHERE   col1 = ''

将返回您设置为空字符串的行。

适用于MySQL,但不适用于Oracle,它不区分空字符串和NULL

Oracle中,后一个查询永远不会返回任何内容。

答案 11 :(得分:0)

使用“”。如果可以断言列非空,则需要较少的编程工作量。这些之间的空间差异是微不足道的。