Nullable与非null varchar数据类型 - 查询速度更快?

时间:2010-06-19 15:08:11

标签: sql

我们通常希望将所有varchar / nvarchar不可为空的与空字符串('')作为默认值。团队中有人建议 nullable 更好,因为:

像这样的查询:

Select * From MyTable Where MyColumn IS NOT NULL

比这更快:

Select * From MyTable Where MyColumn == ''

任何人都有经验来验证这是否属实?

5 个答案:

答案 0 :(得分:12)

在某些平台(甚至是版本)上,这取决于NULL的索引方式。

我对NULL的基本经验法则是:

  1. 在对齐之前不允许使用NULL

  2. 除非数据确实未知,否则不允许使用NULL

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

    与中间名/姓名相似。有些人没有。这有什么不同,它是不知道的,你在乎吗?

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

    所以对我来说,是否允许NULL将首先取决于数据的语义 - 性能将是第二位,因为数据被错误解释(可能由许多不同的人)通常比性能更昂贵的问题。

    它可能看起来像一个小东西(在SQL Server中,实现是与行一起存储的位掩码),但在理由之后只允许NULL才能让我发挥最佳效果。它在开发早期捕获事物,迫使您解决假设并理解您的问题域。

答案 1 :(得分:5)

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

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

答案 2 :(得分:4)

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

至于表现,“它取决于”

如果您有varchar,则在行中存储实际值以获取长度。如果你有char,那么你存储实际长度。 NULL不会存储在行内,具体取决于引擎(例如,SQL Server的NULL位图)。

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

因此,您的同事部分正确,但可能不会完全欣赏它。

盲目地使用空字符串是使用sentinel值,而不是使用NULL语义问题

FWIW和个人:

  • 我会倾向使用NULL但不总是。我喜欢避免像9月31日这样的日期,这是禁止空虚的地方。

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

  • Sentinel值比NULL更差。魔术数字。任何人

答案 3 :(得分:2)

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

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

他可能意味着很好,并希望将他的知识贡献给团队。不幸的是,他错了。从基准是否会证明他的陈述正确或不正确的意义上来说并没有错。他认为这不是你设计数据库的方式,这是错误的。是否使字段为空的问题是关于数据域的问题,以便定义字段的类型。它应该根据对该领域没有价值的意义来回答。

答案 4 :(得分:1)

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