2010-06-19 71 views
9

我们一般宁愿将所有varchar/nvarchar列为不可空的,并将空字符串('')作为默认值。在球队有人建议可空更好,因为:可为空或非空varchar数据类型 - 查询更快吗?

这样的查询:

Select * From MyTable Where MyColumn IS NOT NULL 

比这个速度更快:

Select * From MyTable Where MyColumn == '' 

任何人有任何的经验来验证这是否是真正?

+0

至少在Oracle下,空字符串也被视为NULL。 – zneak 2010-06-19 15:11:03

+0

我的经验:不在MySQL下。 – MvanGeest 2010-06-19 15:14:06

+2

你的例子不一样。第一个应该是'MyColumn IS NULL',或者第二个应该是'MyColumn <>'''。 – 2010-06-19 15:17:51

回答

12

在某些平台(甚至是版本)上,这将取决于如何对NULL进行索引。

我的经验为空值的基本规则是:

  1. 不允许NULL直到有道理

  2. 不允许NULL,除非数据能真正是未知

一个很好的例子就是建模地址线。如果你有一个AddressLine1和AddressLine2,第一个有数据,第二个NULL是什么意思?在我看来,你要么知道地址,要么在一组数据中有部分NULL,只是在有人连接它们并获得NULL(ANSI行为)时要求麻烦。你可以通过允许NULL和添加一个检查约束来解决这个问题 - 要么所有的地址信息都是NULL,要么都不是。

与中间首字母/名称相似的东西。有些人没有。这是不同的,它不知道,你在乎吗?

ALso,死亡日期 - NULL是什么意思?没死?未知的死亡日期?很多时候,单个列不足以在域中对知识进行编码。

所以对我来说,是否允许空值将在很大程度上取决于该语义第一数据 - 性能将是第二个,因为有曲解数据(可能由许多不同的人)通常是昂贵得多问题比表现。

这似乎是一件小事(在SQL Server中,实现是一个与该行一起存储的位掩码),但只有在证明完成后允许NULL才会工作得最好。它在开发早期捕获事物,迫使你解决假设并理解你的问题领域。

+0

至于死亡日期:NULL表示没有已知的日期。在这种情况下,使用空值是有道理的,因为您可能想要查找例如记录的最早日期,或计算死亡人数(NULL不计)。同样的事情适用于中间名,如果你想知道数据库中有多少人拥有这些名称。 – Mewp 2010-06-19 16:04:35

+2

@Mewp你不能算COUNT(DtOfDeath)的人数,总有死人知道他们已经死了,但你不知道死亡的日期(或者这是一个可能的范围 - 正如我们从我们的经验中所知道的卡特里娜之后的新奥尔良)。我的观点是,你必须考虑你想如何使用这些数据,以及你知道为了成功模拟问题域。 – 2010-06-19 16:13:17

5

如果您想知道没有值,请使用NULL。

至于速度,IS NULL应该更快,因为它不使用字符串比较。

2

告诉你的团队中的人过早地优化他的屁股! (但以一种很好的方式)。

像这样的开发人员可能会对团队产生毒害,充满了低级优化的神话,所有这些都可能是真实的,或者在某个特定供应商或查询模式的某个时间点是真实的,或者可能只有真实理论,但在实践中从未如此。处理这些神话是浪费时间的代价,并且可能会破坏其他好的设计。

他可能意味着很好,并希望向团队贡献自己的知识。不幸的是,他错了。从基准是否会证明他的陈述是正确还是错误的角度来看,这并非错误。他错了,因为这不是你设计数据库的方式。是否将字段设置为NULL的问题是为了定义字段类型而针对数据域的问题。应该从这个领域没有价值意味着什么。

1

简而言之,NULL = UNKNOWN!..这意味着(使用死亡日期的例子)该实体可能是1)活着的,2)死亡但死亡日期未知,或3)如果实体是未知的死或生。对于数字列,我总是将它们默认为0(零),因为沿着这条线你可能必须执行聚集计算,并且NULL + 123 = NULL。对于字母数字,我使用NULL,因为它的性价比最低,并且更容易说'... IS NULL'比说'... where a =“”''更容易。使用'... where a =“”[space]'不是一个好主意,因为[space]不是NULL!对于日期,如果必须将日期列留空,则可能需要添加状态指示器列,在上例中,A =活着,D =死亡,Q =死亡,死亡日期未知,N =活动或死者未知。

4

如果您需要NULL,请使用NULL。同上空字符串。

至于性能,“这取决于”

如果你有VARCHAR,您存储行的长度的实际值。如果你有字符,那么你存储实际的长度。取决于引擎,NULL不会被存储在行中(例如SQL Server的NULL位图)。

这意味着IS NULL更快,查询查询,但它可以添加COALESCE/NULLIF/ISNULL复杂性。

所以,你的同事是部分正确的,但可能不完全赞赏。

盲目使用空字符串使用定点值,而再通过空语义问题

FWIW和个人的工作:

  • 我会倾向于使用NULL,但并不总是。我喜欢避免像9999年12月31日那样的日期,这是NULL避免引导你的地方。

  • 从Cade Roux的回答...我也发现关于“死亡日期可以为空”的讨论毫无意义。实际上,对于一个领域来说,要么有价值要么没有价值。

  • 哨兵值更糟,然后是NULL。魔术数字。任何人?

+0

9999年12月31日,在我继承它的数据库中是1/1/1900,非常烦人。 – AMissico 2013-07-24 01:21:05

相关问题