规范化需要多长时间?

时间:2009-01-30 17:59:05

标签: sql database-design database-normalization

我有这些表格:

Projects(projectID, CreatedByID)
Employees(empID,depID)
Departments(depID,OfficeID)
Offices(officeID)

CreatedByIDEmployees的{​​{3}}。我有一个几乎每个页面加载的查询。

仅向OfficeID添加冗余Projects列以消除三个连接是不好的做法吗?或者我应该做以下事情:

SELECT * 
FROM Projects P
JOIN Employees E   ON P.CreatedBY = E.EmpID
JOIN Departments D ON E.DepID = D.DepID
JOIN Offices O     ON D.officeID = O.officeID
WHERE O.officeID = @SomeOfficeID

在应用程序编程中,我“首先使用最佳实践编写并在之后进行优化”,但数据库管理员始终警告连接的成本。

13 个答案:

答案 0 :(得分:36)

归一化直到它受伤,然后反规范化直到它起作用

答案 1 :(得分:30)

非规范化具有在大型查询上快速SELECT的优势。

缺点是:

  • 确保完整性需要更多的编码和时间(在您的情况下这是最重要的)

  • DML上的速度较慢(INSERT / UPDATE / DELETE)

  • 需要更多空间

至于优化,您可以优化以获得更快的查询速度或更快的DML(通常,这两个是反对者)。

优化快速查询通常意味着重复数据,无论是非规范化,索引,任何额外的表格。

如果是索引,RDBMS会为你做,但在非规范化的情况下,你需要自己编码。如果Department转移到另一个Office怎么办?你需要在三个表而不是一个表中修复它。

所以,正如我从你的表名中看到的那样,那里不会有数百万条记录。因此,您最好将数据标准化,管理起来会更简单。

答案 2 :(得分:9)

在必要时始终规范化以消除数据库完整性问题(即可能存在重复或丢失的数据)。

即使非正规化带来性能提升(通常情况并非如此),但丢失数据完整性的代价太高而无法证明其合理性。

只要问一下那些不得不努力解决遗留数据库中所有模糊问题的人,无论他们是喜欢好数据还是无关紧要(如果有的话)加速。

此外,如John所述 - 如果您最终需要非规范化数据(用于速度/报告/等),则在单独的表中创建它,保留原始数据。

答案 3 :(得分:7)

加入的成本本身不应该让你太担心(除非你试图扩展到数百万用户,在这种情况下你绝对应该担心)。

我会更关注对调用此代码的代码的影响。规范化数据库更易于编程,并且几乎总是在应用程序本身内提高效率。

那就是说,不要超越理性的范围。我已经看到了规范化的规范化,它通常最终出现在一个数据库中,该数据库有一个或两个实际数据表,而20个表只填充了外键。这显然是矫枉过正的。我通常使用的规则是:如果列中的数据会被复制,则应对其进行规范化。

答案 4 :(得分:4)

如果你的数据库没有正确规范化,那么DBA应该会担心。在仔细测量了性能并确定你有瓶颈后,你可能会开始非正常化,但我会非常谨慎。

答案 5 :(得分:3)

最好将该架构保留在第三范式中,让DBA抱怨连接成本。

答案 6 :(得分:3)

我非常关心那些警告你加入费用的DBA,除非你处于高度病态。

答案 7 :(得分:3)

在尝试其他所有事情之前,你不应该看看非规范化。

这的表现真的是一个问题吗? 您的数据库是否具有可用于加快速度而不影响完整性的任何功能? 你可以通过缓存来提高你的表现吗?

答案 8 :(得分:2)

如果您使用整数(或BIGINT)作为ID,并且它们是群集主键,那么您应该没问题。

虽然从项目中找到办公室似乎总是更快,因为你总是查找主键,但是外键上的索引的使用会使差异最小,因为索引也会覆盖主键。

如果您以后发现需要对数据进行非规范化,则可以按计划或触发器创建缓存表。

答案 9 :(得分:2)

标准化以模拟设计中的概念及其关系。想一想关系可以改变什么,以及这样的改变对你的设计意味着什么。

在您发布的模式中,有一些看起来像是一个明显的错误(如果您的组织工作方式有特殊情况,这可能不是错误) - 隐含的假设是每个部门只有一个办公室,同一部门的所有员工都在那个办公室工作。

如果部门占据两个办公室怎么办?

如果员工名义上属于一个部门,但在不同的办公室工作(假设您指的是实体办公室),该怎么办?

答案 10 :(得分:1)

在给定的索引示例中,在表上正确设置索引应该允许联接发生得非常快,并且可以很好地扩展到100,000行。这通常是我解决这个问题的方法。

有时候,数据会被写入一次,并且会在剩下的时间内被选中,而每次进行十几次连接真的没有意义。

答案 11 :(得分:1)

不要反规范化。

根据简单而完善的设计原则设计您的表格,以便轻松实现系统的其余部分。易于构建,填充,使用和管理数据库。轻松快速地运行查询和更新。当情况需要时,易于修改和扩展工作台设计,并且由于轻微和瞬态原因,不需要这样做。

一套设计原则是规范化。规范化导致表格易于更新(包括插入和删除)。规范化避免了更新异常,并且避免了与自身矛盾的数据库的可能性。这可以通过使它们变得不可能来防止大量的错误。它还可以通过使它们变得不必要来防止大量更新瓶颈。这很好。

还有其他一套设计原则。它们导致桌面设计不完全标准化。但这不是“非规范化”。它只是一种不同的设计,与标准化有些不相容。

一组设计原则导致与标准化完全不同的设计是星型模式设计。星型模式对查询来说非常快。考虑到良好的DBMS,良好的物理设计和足够的硬件来完成工作,即使是大规模的连接和聚合也可以在合理的时间内完成。正如您所料,星型模式会受到更新异常的影响。当您使数据库保持最新时,您必须围绕这些异常进行编程。您通常需要一个严格控制且精心构建的ETL过程,以便从其他(可能是规范化的)数据源更新星型模式。

使用存储在星型模式中的数据非常简单。使用某种OLAP和报告引擎非常容易,您无需编写任何代码即可获得所需的所有信息,而且不会过多牺牲性能。

设计良好的规范化架构需要进行良好且深入的数据分析。数据分析中的错误和遗漏可能导致未发现的功能依赖性。这些未被发现的FD将导致不知情的偏离正常化。

设计和构建良好的星型模式还需要进行良好且深入的数据分析。数据分析中的错误和遗漏可能导致维度和粒度的不幸选择。这将使ETL几乎不可能建立,和/或使明星的信息承载能力不足以满足新兴需求。

良好而有些深入的数据分析不应成为分析瘫痪的借口。分析必须在短时间内正确并合理地完成。较小的项目较短。设计和实现应该能够在数据分析和需求的一些后期添加和更正中存活下来,但不能持续不断地修改需求。

此回复会扩展您原来的问题,但我认为这与数据库设计师有关。

答案 12 :(得分:1)

规范化: 是一项质量决定。

非规范化: 是一项绩效决策。

这就是为什么说 -

  

归一化直到疼痛,去标准化直到它起作用。

以下质量决策告诉您可以使用哪个最低范式:

  1. 对于您的牌桌,多少非冗余很重要?
  2. 您想要多快的数据管理?
  3. 您希望表格之间的关系有多清楚?
  4. 以下效果决策告诉您客户/客户/应用可接受的最高范式:

    1. 我的数据库响应速度是否足够快?
    2. 加入的次数太多导致放缓?
    3. 在您修复了案件中可接受的最低和最高范式后,请在任意位置选择普通表格。