列中的空值何时为“安全”?

时间:2011-01-26 18:19:55

标签: sql mysql sql-server oracle database-design

是否有一般的经验法则来设计数据库以允许列作为空值与3nf规范化?我有一个列,其中列主要由空值(85%)组成,但表大小不超过10K记录(不是很大)。它主要用于记录和记录保存,因此大多数事务将是插入和选择,没有更新。我正在尝试考虑性能和简化设计。在这种情况下,非规范化还是规范化会有很大的好处吗?不同的RDBMS表现不同吗?

11 个答案:

答案 0 :(得分:7)

避免使用NULL有三个不同的原因。按重要性排序(当然,我认为):

  1. 您想要正确建模数据。

  2. 您希望提供一个可以轻松生成正确应用程序的数据库。

  3. 您想节省磁盘空间。

  4. 你关注的是表现。

  5. 好的,有四个单独的原因!

    在这四个中,我非常关注#1,非常关注#2(特别是因为我也一直是程序员)而且我真的不太关心#3,因为磁盘空间很便宜还因为#1和#2为我删除了任何数据库中的大多数NULL。至于#4,我从不想牺牲性能的正确性 - 如果我不能确信这是正确的,我得到答案的速度并不重要。如果我无法在模型良好的SQL数据库中实现我的性能目标,那么SQL数据库可能是错误的工具。

    因此,对我来说最重要的问题是“单表方法是否正确地为您要存储的数据建模?”同样重要的是“单表方法是否会使编写错误代码对数据库变得太容易?”我想强迫自己(或任何追随我的程序员)拥有将数据放在正确的位置。查看您的数据并回答这些问题,它可以帮助您确定正确的结构。

答案 1 :(得分:2)

您是在谈论允许用户存储NULL而不是空字符串或数字的表吗?

如果是这样,我会说如果NULL具有特殊含义(不仅仅等于空字符串''或0),则应该只允许列中的NULL值。

答案 2 :(得分:2)

记录表应该作为一般规则进行非规范化,因为您对事件时的事物状态感兴趣并且您不希望只保留外键到任何东西因为它可能已经改变了。

但是,我在这里看不到NULL与规范化有什么关系?

答案 3 :(得分:2)

NULL表示'缺失或未知'。这与标准化无关。它与属性的域有关。如果属性是必需的,则它是非空的(例如,EmployeeName可能是Employee属性的必需属性)。如果属性是可选的或者是非必需的(例如,并非所有员工都有 - 或者愿意与他们的老板共享 - 家庭电子邮件地址),那么列EmployeeHomeEmailAddress应该可以为空。

该列本身是否恰当地是表的一部分取决于其语义。可空列不一定(尽管可能)表示设计问题 - 也许它应该是模型中自己的实体,与父实体的基数为0:1或0:M。也许它不应该。这一切都取决于实体和属性的语义。但是你不能只是做一个可空的列==非规范化数据:这样会导致疯狂。

答案 4 :(得分:2)

底线:如果您希望真正的数据结构规范化为第3范式,则不得包含空列。

如果你像我们其他人一样在现实世界中生活和工作,你会发现可以为空的列完全可以接受和“安全”。您的数据库在技术上不会被规范化,但真正的数据系统是什么?

很少。

答案 5 :(得分:2)

答案 6 :(得分:1)

当您不总是需要输入时,

nulls是“安全的”。事实上,如果没有真正的默认数据,它们可能是首选。例如,假设您正在跟踪库存,而列是id,长度,宽度,高度,重量

也许你没有得到重视。宽度不应为0,应为null。如果0是您正在跟踪的有效宽度或值,则这尤其相关。

答案 7 :(得分:1)

SQL Server 2008有sparse columnsfiltered indexes来帮助解决这种情况。

答案 8 :(得分:1)

如果我理解您提到的数据规范化不适用于一个表中的每个记录的问题。所以说你的数据库中有一张车辆表,看起来如此:

vehicle
----------------------------
vehicleId int
makeId int not null references make(makeId)
modelId int not null references model(modelId)
numberOfWheels tinyint null
hullMaterialId int null refrences hullMaterial(hullMaterialId)

然后,您可以将其中一些空列标准化为“1到0或1”表,以便更好地了解数据:

roadvehicle
----------------------------
vehicleId int references vehicle(vehicleId)
numberOfWheels tinyint not null

waterVehicle
----------------------------
vehicleId int references vehicle(vehicleId)
hullMaterialId int not null refrences hullMaterial(hullMaterialId)

(请原谅简化的例子)

我相信你正在考虑正确的事情。对我而言,如果从设计和域名的角度来看它是有道理的,那么它应该被完成,但我不知道任何经验法则,只是经验。

答案 9 :(得分:1)

关于NULL值我学到了一些东西 - 试图避免重复的答案: - )

此外,维基百科文章NULL: Controversy(以及周边环境)中也提供了相关信息。

并非所有RDBMS系统都表现相同。

在SQL Server中,NULL被视为UNIQUE列/索引中的唯一值。在SQLite a NULL may appear many times and does not count as a duplicate value。显然,SQL92规范在这方面含糊不清。

NULL is NULL -> true(标准和正确)但是NULL = NULL -> ???它应该是假的,但这取决于RDBMS和设置!在SQL Server中,这可以通过ANSI_NULLS设置进​​行控制。如果在不同的上下文中运行,这可能会导致连接异常!根据RDMBS,类似的行为也可以应用于其他操作。 请始终使用/支持正确的SQL相等!

不同的RDBM系统可能也使用不同的物理表布局,当列为NULLABLE时,可能意味着记录中未保留的空间(例如,对于SQL Server中的CHAR(100)XML(存根位),这是正确的。如果在初始创建后需要更新此记录(例如,最初为NULL),则此 会导致在某些情况下过多的碎片。但是,这应该只是需要注意的事项,我会犹豫是否根据这样的实现细节做出一般的决定,因为还有其他因素在起作用!

确保定义NULL意味着

不幸的是,没有NOTSETINVALID值来补充NULL。每列应具有NULL定义的特定含义。是指“无效价值”还是“未指定价值”或“价值不知道”等?可能需要将NULLnon-NULL sentinel值混合(或者根本不使用NULL或使用其他状态列/关系)来实现正确的业务逻辑。

快乐的SQL'ing。

答案 10 :(得分:0)

在表设计时,如果您希望85%的值对于特定列可以为null,则最好保留在另一个表中。 [基于标准化]为表记录分配的数据块可以基于为每列指定的字节计算。 [像C中的malloc函数]。这可能会导致行链接。