【问题标题】:Add a boolean field vs check if field IS NOT NULL?添加一个布尔字段与检查字段是否为空?
【发布时间】:2017-06-20 15:03:39
【问题描述】:

我们使用需要管理员批准记录才能公开显示的表格。我想知道最合适的方法是设计这样一个表,其中主要查询是检索已批准(或尚未批准)的记录。

假设查询的列会被索引:

  1. 使用布尔字段对速度有什么好处?
  2. 检查列是否为 NULL 是否违反最佳实践?

例如:

id | title | text | approved_dttm
---------------------------------------
1  | ...   | ...  | null 
2  | ...   | ...  | 2017-01-01 00:00:00 ETC


SELECT * FROM table where approved_dttm IS NOT NULL; 

id | title | text | approved | approved_dttm
---------------------------------------
1  | ...   | ...  | 0        | null 
2  | ...   | ...  | 1        | 2017-01-01 00:00:00 ETC


SELECT * FROM table where approved = 1; 

注意:除了已批准/未批准之外,我们不需要多个状态。没有“需要进一步审查”等。

【问题讨论】:

  • 恕我直言,坚持批准日期,布尔值添加冗余数据(如果设置了批准日期,则必须批准)。 NULL 的使用非常广泛,人们经常使用它。
  • 您将如何处理已批准但您无法使用已批准的_dttm?如果答案是什么,我会放弃它。

标签: mysql database database-design


【解决方案1】:

问:使用布尔字段对速度有什么好处?

答:没有。

在这种情况下,使用approved 列与approved_dttm IS [NOT] NULL 相比,任何查询都不太可能获得“速度优势”。

虽然批准列的额外字节可以忽略不计(假设它被定义为 TINYINT,但额外的字节不会真正影响“适合”块中的行数)... 索引 在该列上将不可忽略。这将需要额外的块(空间),并且会增加维护索引条目的开销。

我们不能排除添加该列会带来好处的一些特殊极端情况,但总的来说,鉴于所提供的信息,不,添加该列没有“速度优势”。

(我们在这里搁置冗余数据和更新异常的讨论......添加(冗余)approved 列与第三范式相悖,并且熟悉的口头禅“每个属性都依赖于钥匙,整个钥匙,只有钥匙。所以帮帮我,Codd”。)

问:检查列是否为 NULL 是否违反最佳实践?

答:没有。

它不违反我所知道的任何“最佳实践”。 NULL 和三值布尔逻辑一直存在(自从 1970 年 E.F.Codd 首次创造“关系”,1977 年 System/R 和 Oracle 以及 1983 年 DB2 的出现......)

某些应用程序开发人员可能不喜欢(或不理解)如何处理 NULL 值的细微差别。确实,将列定义为 NOT NULL 可以在一定程度上减轻他们的负担。但在我的书中,“避免处理 NULL”不是“最佳实践”。

我们确实注意到一些数据库实现存在一些怪癖,没有使用索引来满足col IS NULL 谓词。但是这些怪癖通常可以通过适当定义的索引和精心编写的查询来克服。了解 NULL 值及其怪癖并处理它是“最佳实践”。

【讨论】:

    【解决方案2】:

    1) 添加approved 字段只是复制了可以从approved_dttm 派生的信息,因此从信息的角度来看添加它是没有意义的。

    2) 从索引的角度来看,您可能会争辩说,布尔(嗯,tinyint)字段上的索引小于日期时间字段的索引。但是,这个索引的选择性会很低(只有 2 个可能的值),因此 MySQL 在实际选择数据时很有可能会忽略这个索引。

    总而言之,我不会添加额外的布尔字段来指示条目是否被批准。

    【讨论】:

      猜你喜欢
      • 2022-07-31
      • 1970-01-01
      • 1970-01-01
      • 2014-02-02
      • 2012-02-21
      • 2011-06-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多