數據庫設計中的 9 大常見錯誤

數據庫設計中的 9 大常見錯誤

作為數據庫設計人員,當我們負責數據庫項目時,在數據庫設計以及把數據庫部署到生產環境的過程中可能會遇到一些挑戰。

其中一些問題不可避免,也無法控制。但是,其中相當一部分可以追溯到數據庫設計本身的質量。我們在初步階段所做的決定會對數據庫最終的工作情況有深遠的影響。

糟糕的預規劃

如果我們要建一所房子,我們不會聘請一位工程承包商,然後馬上就要求他們開始打地基。這會導致災難發生。至少,我們需要就建房計劃和藍圖達成一致。數據庫設計也一樣。我們規劃得越好,設計的輸出質量就越高。

好的數據庫是深思熟慮的結果,而不是臨時想法的集合。糟糕的設計規劃會導致結構性問題,該數據庫一旦推出後,要解決這些問題是相當昂貴的。我們不可能總是能預測到數據庫會遇到的所有問題,但是好的規劃確保我們可以把問題減少到只有那些真正無法避免的問題。

未能理解數據的用途

創建數據庫的目的相當廣泛。從存儲個人私人信息的小型數據庫到處理海量信息的大規模企業數據庫。設計人員必須明白數據庫的目的所在,以便用最符合這些目標的方式來設計。

要問的關鍵問題包括:數據的性質、數據獲得的方式、數據存儲和檢索的頻率、數據的規模、使用數據的應用程序是什麼。在工作日結束時手動輸入數據的數據庫和實時捕獲並自動存儲數據的複雜的行業數據庫不能用同一種設計模型。

設計的關鍵是確保數據效率、可用性和安全性的(請參考PostgreSQL 安全)。忽略數據的目的將導致設計看上去符合所有的條條框框,但實際上是不健全的。

規範化不足

數據庫設計不是一個嚴格確定的過程。兩個遵循同樣設計規範的開發人員最終可以設計出兩個截然不同的數據庫。這主要是因為任何軟件工程項目都固有的創造性。儘管如此,設計的一些核心原則對確保數據庫以最佳方式運行至關重要。其中之一就是規範化。規範化指的是用於把表分解成組成部分的技術。我們執行該操作,直到我們讓每一張表只表示一種事物,而列描述該表所代表的項的屬性。規範化是一種古老的計算概念,已經有 30 多年的歷史了。事實上,SQL 主要用於讀取和操作規範化數據集。為了理解規範化,有必要了解 SQL 的工作原理。

SQL 本質上是一種迭加式語言,適用於輕鬆創建結果集或值集。使用 FROM 子句,我們可以從一張表中提取數據,並使用 JOIN 把數據添加到另一張表的內容中。我們可以使用幾乎無限數量的表來生成我們需要的數據。SQL 的迭加能力對數據庫開發和性能來說都至關重要。

當索引與鍵值完全同步時,索引效果最佳。當我們必須使用 LIKE、CHARINDEX、SUBSTRING 及類似命令來解析值與列值的組合時,SQL 範式遭到破壞,數據可搜索性變差。

因此,規範化我們的數據庫對簡化開發和始終如一的高性能至關重要。儘管如此,規範化還是有很多層次的,而且存在過度規範化的數據庫。良好的規範化平衡了記錄插入、更新、查詢和刪除的需求。採用最廣泛的最佳實踐是,數據庫必須至少規範化到第三範式(Third Normal Form,簡稱 3NF)。但是,第四(4NF)和第五(5NF)範式也相當有用,容易理解,也值得我們努力瞭解如何使用它們。

冗餘記錄

冗餘表和字段對數據庫設計人員和管理員來說是噩夢。它們需要佔用系統資源才能保持安全、更新和備份。當我們討論十多個記錄時,冗餘記錄也許看起來不多。但是,在大型數據庫中,冗餘字段可以是數千個或數百萬個,計算資源開銷很大。它們不必要地增加了數據庫的規模,降低了效率,增加了數據崩潰的風險。

當然,有時候冗餘也許是必要的,但是,這應該是例外,而不是規則。即使允許冗餘,也應當清楚地記錄理由,以確保將來該理由不再有效時,數據庫管理員可以刪除冗餘。

糟糕的索引

有時候,用戶或應用程序可能需要查詢一張表中的多個列。隨著表中行的數量的增長,用於完成這些查詢的時間也在穩步增加。為了加速查詢並減少表規模的影響,謹慎的做法是索引表的列,以便在調用 SELECT 查詢時,每個列中的條目幾乎可以立即獲得。

不幸的是,加速 SELECT 函數通常會導致更常規的 INSERT、UPDATE 及 DELETE 命令的性能惡化。這很大程度上是因為索引本身必須不斷地與數據庫的內容保持同步,而這又意味著大量的數據庫引擎開銷。因此,具有諷刺意味的是,我們加速 SELECT 查詢的嘗試可能導致整個數據庫變慢。這是過度索引的經典案例。

對所有列只提供一個索引,並且該索引和查詢表所用到的主鍵不同,這種方法可以解決這個問題。我們也可能按最常用到最不常用對列進行排序。索引始終是一個微妙的平衡,歸根結底要用對。

所有域值的一個表

包羅萬象的域表不是數據庫設計的最佳方法。請記住,關係數據庫的構建思想:數據庫中的每個對象只代表一個事物。任何數據集所代表的事物都不應該含糊不清。通過查看主鍵、表名、列名和關係,我們應該可以快速解讀數據集的意義。儘管如此,對於數據庫設計,一種揮之不去的誤解是,表越多,數據庫就越混亂越複雜。

通常,把幾張表壓縮到一張表中就是簡化設計的原理。這聽上去是個好主意,但是,通常得到的是效率低下且難以操作的數據庫。SQL 代碼將變得很長,難以閱讀,也不自然。這將把兩種截然不同的東西混在一起。乍一看,域表看起來像一個抽象的文本容器。從實現的角度來看,這是正確的,但是,這不是設計數據庫的最好方法。

作為規範化過程的一部分,隔離和分解數據最終形成每一行只代表一個事物。每個域表與所有其他域表都不同。

多個域表的最終結果是:

  • 使用在查詢中的數據變得更容易。
  • 可以更自然地用外鍵約束來驗證數據,這對單域表設計來說是不切實際的。我們可以用單域表來做,但是每張表所需的鍵將使維護變成雷區。
  • 無論何時我們需要添加與某個對象相關的更多數據,該任務就像添加一個或多個列那樣簡單。
  • 小型域表可以放入硬盤的單個頁中,而不像大型域表需要分散在多個硬盤分區中。表存放在單個頁中意味著可以用單次硬盤讀來完成數據提取。
  • 擁有多個域表並不妨礙我們對所有行使用一個編輯器。域表最有可能擁有相同的底層用法 / 結構。

糟糕的或不一致的命名約定

數據庫設計人員和開發人員常常把他們的角色完全看作是技術角色。非技術方面(如遵守命名約定)往往被推到優先級列表的較低位置,或者甚至完全被忽略。這可能是個災難性的錯誤。

命名也許是設計人員自行決定的,但是,事實上,它是數據庫文檔的第一個也是最重要的元素(我們接下來將探討文檔錯誤)。數據庫設計人員應該把他們的工作看作是在他們換了僱主或角色之後還將繼續存在的東西。命名約定的目的是,讓沒有完全參與該項目的人也能比較容易地快速理解表和列的內容。未來的管理員、開發人員或用戶不應當必須看完長長的文檔才能理解某個表名或列名的意義。表如何命名的具體細節並未得到業界的一致同意。

最重要的是一致性。一旦我們遵循某個特定的風格來命名對象,那麼在整個數據庫中要堅持使用它。表名必須儘可能是表所代表的內容的完整或簡約描述,而列名應該清楚地表明其所代表的信息。對於簡單數據庫,這並不難。但是,一旦我們構建彼此引用的表,事情就變得複雜了。嚴格遵循命名約定始終是正確的方向。

這樣的約定包括沒有列或表名的字符長度限制,以消除使用不易理解或記憶的首字母縮略詞的需要。如列名 CUST_DSCR,任何人讀到這個名字都將不得不猜測該列包含的內容。CUSTOMER_DESCRIPTION 則是個更好的列名,沒有迫使讀者展開他們的想象力。

避免冗餘:在一張名為“Students(學生)”的表中,我們不必把列命標成 StudentName、StudentAddress 或 StudentGrade,因為 Name、Address 和 Grade 已經足夠了。還有,不要使用保留字。用“Index”來標記某列會讓人困惑,也會成為錯誤的來源。可以用一個描述性的前綴,如 StudentIndex。

糟糕的文檔

如果數據庫開發人員和設計人員在確定命名約定的優先級上碰到問題,那麼他們在文檔方面就會存在更大的問題。對於開發人員來說,文檔有時感覺像是開發過程中一個微不足道的非必要方面。然而,很多在其他方面設計優秀的數據庫已經犧牲在糟糕文檔的祭壇上。糟糕的文檔極大地抑制了故障排除、結構改進、升級和連續性。

數據庫設計人員必須始終想象他們會在某個時刻不再參與對該數據庫的支持。文檔應該讓其他人容易接手數據庫設計、開發或管理。良好的文檔必須包含列、表、關係和約束的定義,使之清楚地表明每個元素應該如何使用。如果我們可以包含示例以說明預期值,那麼效果會更好。

有些設計人員會使用糟糕的文檔作為確保工作安全性的一種手段,即除了他們之外,沒有人能完全理解該數據庫。這是一種短視和註定失敗的策略,因為這幾乎總是導致管理層看透設計人員的意圖。糟糕的文檔還讓我們作為設計人員多年後返工或改進這些代碼變得非常困難。

測試不充分

我們可以仔細地完成世界級數據庫設計所要求的所有步驟。但是,如果我們沒有對數據庫進行嚴格的測試,那麼我們將陷入黑暗之中。不幸的是,當項目延期時,測試階段受到的影響最大。這是弄巧成拙,因為一個快速通過的數據庫會立即被錯誤及不一致性所困擾,而這些錯誤應該很容易在測試階段被識別和解決。

一個滿是缺陷的數據庫不會讓用戶和管理員喜歡,即使最終修復了錯誤,我們也擺脫不了不好的名聲。在數據庫上線前,進行深入而廣泛地測試,這將大大減少部署到生產環境中後產生的故障的數量和規模。良好的測試不會找到每個錯誤,但是肯定有助於擺脫大多數錯誤。

結論

數據庫開發和設計是任何數據密集型項目的核心,這些項目幾乎包含了所有業務應用程序。因此,設計過程應該始終在此上下文中進行審查。本文中列出的設計錯誤一開始會被看作是小而不起眼的問題。然而,最終,它們會極大地降低數據庫性能並且修復成本高昂。要從一開始就正確地做事,增加構建非常適合其預期目的數據庫的幾率。

閱讀英文原文:9 of the Most Common Mistakes in Database Design


分享到:


相關文章: