我在mysql中有一个数据库表,根据一个新特性,我们可以用两种方式实现-1。或者在同一个表中创建一个新的列(可以为null),这种方法的缺点是-这个列将有95-98%的时间为null。2使用已有表的外键创建一个新表。
所以这两个架构看起来像这样-
1. table1 - <id, ..., new_column>
2. table1 - <id, ...>, table2 - <id, table1_id, ...>
第一种方法遵循非规范化方法,而第二种方法遵循规范化方法。但由于这是一个实际问题,所以有时可以采用非规范化方法。
我对db设计的一些假设可能是错误的,您认为解决此类问题的更好方法是什么?
2条答案
按热度按时间omqzjyyz1#
在这些情况下,“垂直分割”可能是有利的
第二个表中的列通常缺失,因此该表的行数较少。注意:您可以
NULL
通过使用LEFT JOIN
.第二个表中的列很庞大,但很少使用。执行此操作时存在性能缺点
SELECT *
有些柱子是TEXT
/BLOB
. 垂直分区可以帮助您提高速度(选择合适的ROW_FORMAT
在innodb中几乎消除了这一优势。)最常见的查询不需要第二个表的列。
你必须在不停机的情况下添加列。一
ALTER .. ADD COLUMN ..
在主表上,根据mysql/mariadb版本,可能会长时间阻止使用它。我怀疑每100张table中只有1张应该这样分开。我上面列出的好处是罕见的,这些好处可能不足以证明我的努力是正确的。
第二张table也一样
PRIMARY KEY
作为主桌,但没有AUTO_INCREMENT
. 这两个表将不具有相同的辅助键。请注意,组合索引不能同时包含两个表中的列。如果新列是一堆“属性”,例如在“商店”应用程序中,请考虑将它们放入
JSON
列。这是开放式的,但使用起来很笨拙WHERE
或者ORDER BY
.lsmd5eda2#
如果你能提供一些具体的例子,这将非常有帮助-“我应该添加一个可能为空的列吗”不容易回答。
一般来说,正常化,直到你能证明你必须做其他事情。设计你的数据库的易读性和防虫性;添加一个额外的表要比弄清楚为什么应用程序在12个月内突然报告不正确的数据要省力得多,因为您更改了一点代码,却意外地忘记了非规范化。
那么,这个可为null的列是实体的属性吗?不是全部
people
有一个middle name
属性-拥有一个可为null的列是完全合理的。或者它只是因为方便而附加到实体,但实际上不是一个属性?例如,一个
person
可能有一个employer
,而该雇主可能有address
; 理想情况下,你应该创建一个employer
table,带address
属性;附加employer_address
与人沟通可能会让人觉得是一条捷径(除了地址,我什么都不在乎——我从来不需要知道有多少人为那个雇主工作)。这可能会让人觉得你在为自己节省一些精力——但它不太清晰(因此未来的开发人员会想知道你为什么这么做),更容易出现错误(你可能会得到一个雇主不正确或不一致的地址),而且将来更难更改(祝你好运,仅仅根据地址就可以计算出有多少人为某个雇主工作)。