使用冗余关系是不是很糟糕?

时间:2010-07-27 19:10:11

标签: database database-design relational-database

假设我的数据库中有以下表格:

tables http://www.freeimagehosting.net/uploads/a5ef036857.png

现在我的所有查询都依赖于公司表。为每个其他表提供(冗余)关系以简化我的SQL查询是不是很糟糕?

编辑1:后台是框架的使用问题。请参阅Django: limiting model data

编辑2:没有元组会改变他的公司。

编辑3:我不写mysql查询。我使用抽象层(django)。

7 个答案:

答案 0 :(得分:7)

这是不好的做法,因为您的冗余数据必须独立更新,因此必须冗余。一个充满潜在错误的过程。 (甚至必须单独分配和维护自动级联)

通过引入此关系,您可以有效地对数据库进行非规范化。为了提高性能,有时需要进行非规范化,但从您的问题来看,这听起来只是简化了SQL。

使用其他机制来抽象数据库的复杂性:视图,存储过程,UDF

答案 1 :(得分:5)

您要问的是您的设计是否违反第三范式。如果没有充分的理由,这样做是不可行的,因为通过创建冗余,您可能会在数据中出现错误和不一致的可能性。此外,使用冗余数据“简化”模型以支持某些操作可能会使其他操作复杂化。此外,可能需要不必要地复制约束和其他数据访问逻辑。

答案 2 :(得分:4)

  

为了简化我的SQL查询,为每个其他表提供一个(冗余)关系是不好的做法?

是的,绝对是,因为当您将关系客户更新为公司或部门更改为公司时,这意味着更新每个冗余关系 - 如果您错过任何此类更新,您现在拥有一个充满冗余数据的数据库。这是一个糟糕的非规范化。


如果您只想简化SQL,请考虑使用视图“带来”父数据。这是一个通过客户加入将company_id拉入合同的视图:

create view contract_customer as
select 
  a.*, 
  b.contract_id, b.company_id
from 
  contract a 
  join customer b on (a.customer_id = b.customer_id);

这种联接很简单,但为什么要一遍又一遍地重复呢?写一次,然后在其他查询中使用该视图。

如果你没有根据视图在查询的select列表或where子句中放置任何客户列,那么很多(但不是全部)RDBMS甚至可以优化连接,只要你使contract.customer_id有customer.customer_id上的外键引用完整性约束。 (如果没有这样的约束,就不能省略连接,因为然后可能存在一个在客户中不存在的contract.customer_id。因为你永远不会想要那个,您将添加外键约束。)

使用视图实现了你想要的,没有必须更新子表的时间开销,没有通过添加冗余列使子行更宽的空间开销(当你有很多行时,这真的开始很重要,因为行越宽,一次可以容纳到内存中的行就越少,最重要的是,当父进程更新但子进程没有时,数据不一致的可能性不大。

答案 3 :(得分:4)

如果你真的需要简化一些事情,那么View(或多个视图)会派上用场。

在员工视图中为公司提供一个列不会很难规范化,前提是它来自一个连接部分。

答案 4 :(得分:2)

如果您的意思是在每个表中添加公司列,那么这是一个坏主意。它会增加数据完整性问题的可能性(即它会在一个表中更改,但不会在其中应用的其他6个表中更改。)

答案 5 :(得分:1)

我不是说在OP的情况下,但有时它很有用(就像goto;)。

一则轶事:

我正在使用一个数据库,其中大多数表都有一个指向帐户根表的外键。帐号在数据库外部,一旦发布,不允许更改。因此,没有更改帐号的危险,也无法更新数据库中的所有引用。我还发现从帐号中键入的表中获取数据也相当容易,而不必在层次结构中进行复杂且昂贵的连接以访问root帐户表。但在我的情况下,我们没有那么多的外键作为外部(即真实世界)标识符,所以它与OP的情况并不完全相同,似乎适合例外。

答案 6 :(得分:-1)

这取决于您对“效果”的功能要求。您的应用程序是否会处理大量需求?简化JOINS拥有卓越的性能。除了硬件便宜,周转时间也很重要。

您在数据库常规表单中的深度越深 - 您节省空间但计算量很大