2009-01-30 79 views
18

我有這些表:(「CreatedByID」是foreign key員工)在數據庫設計中採取規範化有多遠?

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

而且我有一個查詢,我需要爲Web應用程序的幾乎所有要求,抓住所有運行項目在辦公室。僅僅爲項目添加一個冗餘的「OfficeID」列以消除三個連接是不好的做法?或者我應該做以下事情?

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 

直到我注意到性能問題?在應用程序編程中,我總是遵循「先用最佳實踐編寫,然後再優化」的規則,但是當涉及到這樣的數據庫設計和規範化時,我會擔心,因爲數據庫管理員總是警告連接的成本。

+2

我試圖讓SQL顯示格式,但stackoverflow編輯器一直把它放在一行。 – Element 2009-01-30 18:05:23

+0

縮進這些具有四個空格的行,使其顯示爲「代碼塊」。 – 2009-01-30 18:09:05

+0

您需要更好的dbas,數據庫中預計會有連接,並且它們已經過優化以使用它們。如果你的dbas沒有索引(FKS需要索引)或者數據很大,它們的成本非常高。即使在那裏,我也知道數據庫的大小是terrbytes,並且仍然使用連接。 – HLGEM 2013-08-07 17:17:58

回答

29

反規範化在大型查詢上具有快速SELECT的優勢。

缺點是:

  • 它需要更多的編碼和時間,以確保完整性(這是最重要的,你的情況)

  • 這是對DML(INSERT/UPDATE/DELETE)

  • 它需要更多的空間

由於FO r優化,您可以優化爲更快的查詢或更快的DML(通常,這兩個是拮抗劑)。

爲更快的查詢進行優化通常意味着複製數據,無論是非規範化,索引還是額外的表格。

在索引的情況下,RDBMS會爲您做,但在非規範化的情況下,您需要自己編寫代碼。如果Department移動到另一個Office會怎麼樣?您需要將其修復爲三個表格而不是一個表格。

因此,正如我從您的表名中可以看到的,那裏不會有數百萬條記錄。所以你最好規範你的數據,它會更簡單的管理。

7

加入成本本身不應該太擔心你(除非你試圖擴展到數百萬用戶,在這種情況下你絕對應該擔心)。

我會更關心對調用此代碼的影響。規範化的數據庫比較容易編程,並且幾乎總是能夠在應用程序本身內提高效率。

這就是說,不要超越理性的範圍來規範化。爲了規範化,我已經看到了規範化的過程,通常結束於具有一個或兩個實際數據表的數據庫,以及僅填充了外鍵的20個表。這顯然是矯枉過正。我通常使用的規則是:如果一列中的數據會被複制,那麼它應該被標準化。

4

DBA的應該關心你的db是否沒有正確的標準化。仔細衡量性能並確定你有瓶頸後,你可能會開始反規範化,但我會非常謹慎。

33

正常化,直到它傷害,那麼非規範化直到它的工作原理

2

如果你使用整數(或BIGINT)作爲ID的,他們是你應該罰款的聚集主鍵。

儘管從項目中找到辦公室似乎總是比較快,因爲您總是查找主鍵,但外鍵索引的使用將使差異最小化,因爲索引也會覆蓋主鍵。

如果您稍後發現需要對數據進行非規範化處理,您可以按計劃或觸發器創建緩存表。

9

爲了消除數據庫完整性問題(即潛在的重複數據或缺失數據),必須儘可能地進行標準化。

即使有來自非規範化(通常並非如此)的性能提升,丟失數據完整性的價格太高的理由。

只要問任何人誰不得不從舊的數據庫修復所有晦澀的問題,他們是否希望良好的數據或者是不重要的(如果有的話)的速度增加工作。

此外,由約翰提到的 - 如果你最終需要去歸一化數據(速度/報告/等),然後在一個單獨的表創建,保存原始數據。

2

規範化以對設計中的概念及其關係進行建模。想想什麼樣的關係可以改變,以及這樣的改變對你的設計意味着什麼。

在您發佈的架構中,有一種看起來像是一個明顯的錯誤(如果您的組織工作方式有特殊情況,這可能不是錯誤) - 有一個隱含的假設,即每部門恰好在一個辦公室,並且所有在同一部門的員工在該辦公室工作。

如果部門佔用兩個辦公室,該怎麼辦?

如果僱員在名義上屬於一個部門,但工程出了不同的辦公室(假設你指的是物理辦事處)是什麼?

1

在正確設置表上應允許連接發生非常快,會很好地擴展到行100,000s的例子給出的指標。這通常是我爲解決問題而採取的方法。

有很多次,雖然該數據被寫入一次,選擇它的餘生它真的沒有意義的,做了十每次連接。

3

最好在第三範式中保留該模式,讓DBA抱怨加入成本。

3

我會最關心的DBA誰警告你關於聯接的費用,除非你處於高度病態的情況。

3

在嘗試其他一切之前,您不應該去看非規範化。

這真的是一個問題的表現嗎? 您的數據庫是否有任何功能可以用來加快速度而不影響完整性? 您可以通過緩存提高性能嗎?

1

不要反規範化。

根據簡單和聲音的設計原則,將可以很容易地實現你的系統的其餘部分設計你的表。易於構建,填充,使用和管理數據庫。方便快捷地運行查詢和更新。在情況需要時易於修改和擴展表格設計,並且由於輕微和短暫的原因而無需這樣做。

一套設計原則是標準化。規範化導致表格更新簡單快捷(包括插入和刪除)。規範化消除了更新異常,並消除了與自身矛盾的數據庫的可能性。這可以通過使它們變得不可能來防止大量的錯誤。它還可以通過使它們變得不必要而防止大量更新瓶頸。這很好。

還有其他一套設計原則。他們導致表格設計不完全正常化。但這不是「反規範化」。這只是一種不同的設計,與標準化有些不兼容。設計原則

一組,導致從正常化一種完全不同的設計是星型架構設計。星型模式的查詢速度非常快。鑑於良好的DBMS,良好的物理設計和足夠的硬件來完成工作,即使是大規模的連接和聚合也可以在合理的時間內完成。正如您所預料的那樣,星型模式遭受更新異常。當您保持數據庫保持最新時,您必須對這些異常進行編程。您通常需要嚴格控制和精心構建的ETL過程,以更新來自其他(可能是規範化的)數據源的星型模式。

使用存儲在星型模式中的數據非常簡單。使用某種OLAP和報告引擎非常簡單,您可以在不編寫任何代碼的情況下獲得所需的全部信息,而且不會犧牲性能。

這需要很好的,有點深的數據分析,設計一個良好的標準化模式。數據分析中的錯誤和遺漏可能導致未被發現的功能依賴。這些未被發現的FD將導致無意中偏離正常化。

它也需要很好的,有點深的數據分析,設計和建造一個良好的星型模式。數據分析中的錯誤和遺漏可能導致維度和粒度的不幸選擇。這將使ETL幾乎不可能建立,並且/或者使得明星的信息承載能力不足以滿足新興需求。

好,有點深數據分析不應成爲分析癱瘓的藉口。分析必須在短時間內完成併合理完成。較小的項目較短。設計和實現應該能夠在數據分析和需求的後期增加和修正之後繼續存在,但不是穩定的需求修訂版本。

此響應擴展了你原來的問題,但我認爲這是相關的將是數據庫設計。

0

標準化:是一個質量決定。

反規範化:是一個性能決定。

這就是爲什麼它說 -

正常化,直到它傷害,反規範化,直到它的工作原理。


以下質量決定告訴這是你可以忍受的至少範式:

  1. 多少非冗餘是你的表很重要?
  2. 你想要多快的數據管理?
  3. 你想要表格之間的關係有多清晰?

以下性能決定分不清什麼是最高範式接受你的客戶/用戶/應用

  1. 是我的數據庫的響應速度不夠快?
  2. 是否有太多連接導致放緩?

後你有固定的最少,在你的情況下,最高的範式可以接受的,挑範式之間的任何地方。