3

在以下情况下:

user has many bags
bag has many items

users
-id

bags
-id
-user_id

items
-id
-bag_id

有两种方法可以访问用户的项目。

1)可以给用户添加一个实例方法,遍历用户的每个包,并将包中的物品收集到一个数组中返回。在 Ruby on Rails 中,类似:

#in user.rb
def items
    items = []
    bags.includes(:items).each { |bag| items += bag.items }
end

2)user_id直接在items表中添加一个属性,并添加一个额外的关系,这样user has many items。然后就做user.items

第二种方法会更快,但涉及存储冗余数据。在某些情况下实施它是有意义的吗?

4

4 回答 4

4

是的,在某些情况下,为了性能而引入一些受控冗余确实是有意义的。通常,只有在数据库无法满足其性能要求时才应该这样做。这称为“非规范化”,您必须考虑的是:

  • 可以使实现更复杂
  • 通常会牺牲灵活性</li>
  • 可能会加快检索速度但会减慢更新速度(因为您现在必须更新多个位置)

因此,在性能不令人满意并且关系具有低更新率和高查询率的情况下需要考虑。

还有一些非规范化的数据库设计,例如星型模式,用于数据库仓库。

于 2013-05-25T19:41:20.083 回答
1

除非有什么你没有告诉我们,像这样的桌子

create table bagged_items (
  user_id integer not null,
  bag_id integer not null,
  item_id integer not null,
  primary key (user_id, bag_id, item_id)
);

至少在 5NF 中。都是关键。那里没有一点冗余数据。

您所做的不是标准化;规范化基于识别某些类型的依赖关系,并通过投影减少它们的影响。你所做的也不是非规范化;非规范化是规范化的撤销。

您只是将主键拆分为多个部分。我不会假装知道你遵循什么原则来证明这一点。它看起来有点像“没有表可能有多个外键”的正常形式。(但是,当然,没有这样的事情。)

于 2013-05-25T23:40:27.170 回答
1

是的。特别是,报告数据库、数据集市和数据仓库经常使用故意偏离某些规范化规则的设计原则。结果是数据库中有一些冗余,但不仅查询速度更快,而且更容易。

当数据库和数据库用户之间存在分析 GUI 时,易于查询尤为重要。如果在数据库设计中遵循某些设计原则,这些分析工具会更容易掌握。规范化在这方面并不是特别有用。

非规范化设计不一定意味着无纪律的设计。特别是,如果您计划构建报告数据库、数据集市或数据仓库,则值得研究星型模式和雪花模式设计。星型或雪花模式保持最新的过程,有时称为 ETL(提取-转换-加载),必须仔细编写,以防止受控冗余导致自相矛盾的数据。

在面向事务的数据库中,规范化通常更好,尽管许多专家并没有试图将它推到 Boyce-Codd 范式之外。

于 2013-05-27T13:23:08.163 回答
0

为了组合来自两个 SQL 表的记录,数据库实现了可以在Ruby on Rails中使用的高效JOIN方法。对于几乎所有应用程序来说,这已经足够快了。话虽如此,对于某些高性能存储,您可能希望按照您的建议存储冗余数据,但这是以必须在写入时保持数据同步为代价的。

于 2013-05-25T19:44:01.527 回答