【问题标题】:Normalize one-to-one boolean relation标准化一对一的布尔关系
【发布时间】:2014-03-17 07:20:24
【问题描述】:

有一张大桌子products。我需要将布尔标志 disabled 添加到我的产品模型中。通常我只会在现有表中添加一个新字段。但是这个属性将很少使用,并且考虑到表中的记录数,这个新字段会对性能和磁盘空间造成不必要的影响。

所以我决定对一对一关系进行一种 1NF 规范化(即将此字段移动到另一个具有引用 products 的外键的表;我不知道它是否真的是 1NF — 这是一部分我的问题)。但我实际上并不需要每个产品的disabled 属性的truefalse 值,因为这意味着关系的表大小将等于products 的大小。所以不需要关系表的值字段。所以我的架构是:

CREATE TABLE products (
  id INT PRIMARY KEY,
  name VARCHAR
);

CREATE TABLE disabled_products (
  product_id INT NOT NULL,
  CONSTRAINT fk_product FOREIGN KEY (product_id) REFERENCES products (id) ON DELETE CASCADE
);

SQLFiddle 摆弄)。

因此,我得到了我想要的——该值仅在设置标志时存储在极少数情况下。在幕后,标志不是由表列表示,而是由给定产品的 disabled_products 中的一条记录表示。

只是想知道我是否做得对。

这种设计有哪些可能的缺点(如果有的话)?

它是否适合关系模型(我指的是这种规范化方式,特别是由单个外键列组成的表)?如果是的话,从 RDB 科学的角度来看,您如何称呼这个解决方案?

【问题讨论】:

  • 这不是反规范化。
  • @ypercube,编辑我的问题的 Jon Hanna 认为是这样。我以为是标准化。
  • 是的,我没有注意到编辑。它现在已在您的原始版本中回滚。

标签: sql database normalization


【解决方案1】:

人们经常问自己是应该拆分一张表还是只创建一个大表。我将在底部谈谈一般逻辑。在您的情况下,这纯粹是一个定义明确的性能计算。

您的解决方案的优缺点 1) 缺点:即使很少禁用记录,您也需要将此表左连接到需要活动记录的每个查询。

2) CON:节省的空间是 1 个字节,这很可能可以忽略不计,所以何必费心。

3) PRO:它使您不必更改可能对您有问题的表。

建议:鉴于上述优点和缺点,我建议您只在表格中添加一个字段。只是一个字节。

一般来说,当修改表不切实际或存在不同类别的记录且每个记录都需要一组特定字段时,或者出于性能原因他们想要对表进行分区时,人们会垂直拆分表。

【讨论】:

  • 谢谢!我唯一能想到的另一个 contra 是实现的相对难度。向 ActiveRecord 模型添加新字段非常容易,但实现这种奇异的规范化并不容易。你给了我更多弃权的理由,所以我想我会选择常规领域。
  • 奇怪的是你有 2) 作为一个 CON,而它是一个 PRO。它节省了一个字节。值不值,那是另外一回事了。
  • 如果 OP 还没有位列,它只会保存一个字节。如果他这样做了,它会进入同一个字节。
【解决方案2】:

可能的缺点很明显 - 与将其存储为列值相比,您不能假设每一行都有一个 disabled 值(因此您必须应用一些自定义逻辑)并且您不能内部连接两个表,因为较小的表会显着减少您的结果集。此外,附加表不包含任何重要信息,但说明了禁用状态,因此纯粹是多余的,但就“有利于性能的冗余”而言,我觉得不知何故想起了星型模式 (http://en.wikipedia.org/wiki/Star_schema)。

【讨论】:

  • 附加表确实包含信息:“产品是否被禁用”。
  • 每一行都有1位信息,怎么可能是纯冗余的呢?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-17
  • 1970-01-01
  • 2017-09-24
  • 2015-05-19
相关资源
最近更新 更多