我在MySQL中有一个数据库表,根据一项新功能,我们可以通过两种方式实现- 1.在同一个表本身中创建一个新列(可为空),这种方法的缺点是-该列将具有95%到98%的NULL条目次数。 2.使用现有表的外键创建一个新表。
所以两种架构看起来都是这样-
1. table1 - <id, ..., new_column>
2. table1 - <id, ...>, table2 - <id, table1_id, ...>
第一种方法遵循非规范化方法,而第二种方法遵循规范化方法。但是由于这是一个现实问题,所以有时可以采用非规范化方法。
在我对数据库设计的某些假设中我可能是错的,您认为解决此类问题的更好方法是什么?
答案 0 :(得分:1)
如果您可以提供特定的示例,这将非常有帮助-“我应该添加一个可能为空的列”很难回答。
用非常通用术语进行归一化,直到可以证明必须做其他事情为止。设计数据库的易读性和防错性;添加额外的表所花的精力要比弄清楚为什么为什么当您更改一些意外忘记了非规范化的代码时,您的应用程序突然在12个月内报告不正确的数据。
那么,此可空列是否是实体的属性?并非所有people
都具有middle name
属性-具有可为空的列是完全合理的。还是因为方便而只是将其附加到实体上,但实际上不是属性吗?
例如,person
可能有employer
,而雇主可能有address
;理想情况下,您将创建一个具有employer
属性的address
表;将employer_address
附加到某人可能会觉得很捷径(除了地址,我不在乎其他任何东西,我永远不需要知道有多少人为该雇主工作)。
这似乎感觉上是您在节省一些时间-但它不太清晰(因此将来的开发人员会怀疑您为什么这样做),更容易发生错误(对于单个雇主而言,您可能会得到不正确或不一致的地址),并且更加困难改变未来(祝您好运,仅根据地址确定有多少人为给定的雇主工作)。
答案 1 :(得分:0)
在这些情况下,“垂直分区”可能是有利的
NULL
来获得LEFT JOIN
。SELECT *
会有性能劣势,并且某些列是TEXT
/ BLOB
。垂直分区可以帮助您提高速度。 (在InnoDB中选择适当的ROW_FORMAT
实际上消除了这一优势。)ALTER .. ADD COLUMN ..
可能会长时间阻止其使用。我怀疑这种方式只能拆分100个表格中的1个。这使读者感到困惑,等等。我上面列出的好处很少,并且这些好处可能不足以证明这样做是合理的。
第二个表将具有与主表相同的PRIMARY KEY
,但没有AUTO_INCREMENT
。这两个表将没有相同的辅助键。并请注意,您不能有一个包含两个表中的列的复合索引。
如果新列是一堆“属性”,例如在“商店”应用程序中,请考虑将它们放在JSON
列中。这是开放式的,但是笨拙地不能与WHERE
或ORDER BY
一起使用。