躲坑!數據庫設計的九大常見錯誤
譯文【51CTO.com快譯】引言:本文向您介紹在數據庫設計中常見的九種錯誤,希望能夠幫你在躲開這些坑點的同時,構建出真正適合項目預期的數據庫。
作為一名數據庫設計人員,在您負責某個數據庫項目時,難免會在初期設計的過程中,以及將數據庫部署到生產環境之后,遇到不同的挑戰。其中的一些很可能源自數據庫的設計疏漏。也就是說,您在初期所做出的某些決策,很可能會對數據庫的最終運行情況產生深遠的影響。因此,為了躲避這些坑點的出現,讓我們來討論一下數據庫設計中常見的九大錯誤吧。
1. 不佳的規劃
正如在蓋房子時,您不可能要求建筑工人在一小時之內就鋪設好地基那樣,您需要事先規劃好房屋的設計圖紙。同理,您對數據庫的初始設計和計劃越周全,您的最終系統和服務的性能才會越好。
因此,一個具有前瞻性的數據庫,絕不是由某些臨時想法拼湊而成。不佳的設計很可能會導致數據庫本身的結構性問題,而一旦它被部署到生產環境中,我們將面臨著替換和調整成本高昂的窘境。雖然我們無法預料到數據庫將來可能出現的每一個問題,但是良好的前期規劃,確實能降低推倒重來的風險。
2. 未能理解數據的意圖
無論是存儲個人數據的小型數據庫,還是處理復雜信息的大型企業級數據庫,每一種類型的創建與使用往往都是為了滿足某個明確的數據意圖。因此,設計人員只有真正理解了數據庫的使用目的,才能根據這些目標進行***匹配模式的設計。
可見,他們需要問出的關鍵問題包括:數據的性質與類型、獲取的方式、存儲和檢索的頻率、數量、以及與之對應的各種應用程序。例如,那些需要在每日下班后手動錄入信息的數據庫,與能夠將數據實時自動地捕獲并存儲的工業級復雜數據庫相比,無論是在設計模型還是數據體量上,都是不一樣的。
因此,設計的關鍵就在于確保數據處置的效率、可用性和安全性(請參見“PostgreSQL安全性”, https://www.datasunrise.com/datasunrise-for-postgresql/)。倘若盲目地追求數據庫的大而全,反而是不切實際,而且不能夠滿足數據的具體應用需求。
3. 標準化不足
數據庫設計并非是一個嚴格確定的過程。遵循相同設計規則的兩位開發人員,往往不一定會設計出相同的數據布局。這主要取決于各種軟件工程項目自身的創新性和數據庫在其中所扮演的作用。盡管如此,一些與設計有關的核心原則,還是能夠對于確保數據庫的***性能起到關鍵性作用的。而其中一項便是:規范化。數據的規范化特指:將數據表分解成為多個組成部分的技術。您可以持續進行此項操作,直到每一個數據表都只表示一種事物,而每一列都只代表該事物的某一項屬性為止。
事實上,SQL主要就是建立在對于規范化數據集的讀取和操作基礎上的。您可以使用FROM子句從一個表中提取數據,并使用JOIN將其添加到另一個表的內容之中。您可以通過生成各種數據表來表示數據的類型。因此,SQL的附加功能對于數據庫的開發和性能都是至關重要的。
索引通過與鍵值的完全同步,來增強其效果。當您必須使用LIKE、CHARINDEX、SUBSTRING、以及類似的命令來解析某一列的組合值時,SQL語句通過分解,以減少數據被搜索的次數。
因此,規范化數據庫對于簡易開發和保持高性能都是至關重要的。我們可以根據不同的標準化水平,來滿足數據庫相關記錄的插入、更新、查詢和刪除等需求。業界廣為接受的***實踐是:數據庫必須至少達到第三范式(Normal Form,3NF)的標準化水平。當然,第四(4NF)和第五(5NF)范式也是非常實用且易于理解的。
4. 多余的記錄
多余的表和字段對于數據庫設計人員和管理員來說簡直是噩夢。它們消耗有限的系統資源,來保障系統整體的安全性、同步性和備份能力。特別是對于某些大型數據庫來說,它們的冗余字段記錄可能會達到幾百萬條,這對于計算資源的開銷顯然是相當龐大的。它們在增加數據庫本身體積的同時,不但降低了系統的運行效率,而且提高了數據受損的潛在風險。
在此,我們并不是說數據記錄的冗余沒有必要,而是說:應當根據規則與策略,在做好相關記錄的基礎上實現數據的冗余,并且在超過保存期限和適用條件時,由數據庫管理員及時予以刪除或銷毀。
5. 不佳的索引
無論是用戶還是應用程序,都可能會需要查詢某個數據表的多個列值。然而,隨著表中行記錄的增加,相應的查詢時間也會隨之穩步上升。因此,為了加快查詢的速度、并減少由表容量所產生的影響,我們需要通過對數據表的列進行索引,以便在調用SELECT查詢時,表中的相對應記錄條目能夠實現“秒回”。
不過對于SELECT函數的加速,通常會導致有更多INSERT、UPDATE和DELETE命令的產生。這很大程度上是因為:索引本身就需要不斷地與數據庫的內容相同步,而此類操作就意味著會產生大量的數據庫引擎開銷。因此,頗具諷刺意味的是:您對加速SELECT查詢的嘗試,可能會反而導致數據庫整體速度的變慢。這正是過度索引的經典案例。
解決上述問題的方法是:為所有列提供單一的索引,以用于查詢表中的不同主鍵。您也可以按照從最常用到最少使用的不同列,進行降序排序。總之,構建索引是門技術活,需要您去花時間總結和調整。
6. 所有域值的單一表
包羅萬象的域表(domain table)并非是數據庫設計的***方法。記住,關系型數據庫的構建理念是:數據庫中的每個對象都只代表一個事物,不可出現任何指代不清的數據集。通過導航主鍵、表名、列名、以及各種關系,應用能夠快速地解讀出數據集的含義。盡管如此,在進行數據庫設計時,許多人總會情不自禁地滑向:數據表越來越多,數據庫越來越復雜和混亂的深淵。
過去,業界的普遍做法是將多張表壓縮到一張表之中,進而簡化設計。但是這往往會帶來效率低下、且難以操作等問題。而且SQL代碼會隨著變長,可讀性也會有所下降??梢妴我挥虮砻菜埔粋€抽象的文本容器,但它的確不是數據庫設計的***方式。
那么,作為規范化的一部分,我們需要通過數據隔離和分解的方法,讓每一行都只代表一個事物,同時讓多個域表相互區別不同的事物。其好處在于:
- 讓數據的查詢更加容易。
- 使用外鍵約束來更自然地驗證數據,而這正是單域表設計所無法實現的。因為在單域表中,每張表所需的各種鍵會變得難以維護。
- 每當您想為某個對象添加多種數據時,您只需簡單地增加一到多列便可。
- 小型域表(small-domain tables)適合于存儲在硬盤的單頁上,而大型域表很可能會擴展到多個磁盤的多個扇區里。顯然,將表存放在單頁中就意味著我們可以通過對單個磁盤的讀取,以快速提取數據。
- 因為這些域表很可能具有相同的底層用法與結構,因此擁有多個域表并不會妨礙您為所有的行啟用同一編輯器。
7.不佳或不一致的命名規則
數據庫設計人員和開發人員經常過于關注自己眼前的技術。而那些命名規則之類的非技術方面,往往會被他們置于優先級列表的***層,或甚至完全被忽略掉。而這恰恰容易造成災難性的惡果。
客觀上說雖然命名規則可以由設計人員自行決定,但事實上,它對于數據庫文檔的重要程度還是不言而喻的(我們將在下面探討不佳的文檔)。由于數據庫設在系統中相對持久和穩定,因此命名規則可以讓那些沒有參與過該構建項目的人員(如:后繼的系統管理員、程序員、甚至是用戶),不需要翻閱上千頁的文檔,就能夠容易且快速地理解數據表與列的含義。當然,關于如何準確地命名各種數據表及其細節,目前業界尚無定論。
因此,最重要的就是要講求“一貫性”。一旦您確定按照某個特定的方式來命名自己的對象,那么就請在整個數據庫中貫徹該規則。對于數據表名稱而言,我們應當盡可能讓它能夠完整或簡約地描述所表示的對象,而每個列的名稱則能夠表示對象的屬性。對于簡單的數據庫來說,這并不難以被實現;而對于需要構建相互引用關系的復雜數據表而言,嚴格遵循命名規則就是一件比較繁瑣的事情了。
值得注意的是:此類規則不應該對列名或表名的字符長度有過分的限制,而且要避免使用那些不易理解、或記憶的首字母縮略詞匯。例如:我們很難猜測出列名為CUST_DSCR的含義;而CUSTOMER_DESCRIPTION則會更好地表示出列名稱的意義。
同時,我們也要避免重復。如果表的名稱為“Students”,那么我們只需采用Name、 Address和Grade作為列名稱便可,而不必重復地使用StudentName、StudentAddress或StudentGrade。當然,我們也不應該擅自使用那些保留詞。如果您將某個列命名為“Index”,那么可能會給系統造成混淆,并產生不必要的錯誤。因此,我們可以使用諸如StudentIndex之類的描述性前綴。
8. 不佳的文檔
我們在上面提到過,數據庫的命名規則往往會體現在相關的文檔中。這些看似微不足道的文檔準備工作,卻時常讓一些優秀的數據庫設計“身敗名裂”。在系統運營的過程中,不佳的文檔會極大地阻礙運維團隊進行各種故障排除、架構改進、升級和連續性保證等工作。
數據庫設計者應當假想:如果自己某一天不再對自己的數據庫提供支持,那么他所準備的相關文檔應該能夠讓其他人輕松地接管后繼的設計、開發或管理工作。因此,良好的文檔必須包含對于各種列、表、關系和約束的定義,明示每一個元素的使用方式。如果您能適當地包含并說明某些預期值的范例,那就更具有參考價值了。
一些設計師可能會狹隘地將晦澀的文檔,作為確保自己工作安全的一種手段,以體現除了自己之外,其他人無法理解目標數據庫的稀缺性。這種短見的做法不但很容易被管理層所識破,而且還會給自己若干年后的系統改造、與代碼改進工作挖下不少的“坑”。
9.不充分的測試
無論是軟件研發也好,還是數據庫設計也罷,都離不開嚴格的測試檢驗??刹恍业氖?,測試階段往往會由于項目截至日期的鄰近,而被無情地跳過。當然,這是一種玩火自焚的做法。一些本該在測試階段被識別和解決的錯誤和不一致性,往往會給上線后的系統埋下各種隱患。
沒有用戶愿意使用、也沒有管理員愿意維護一個填充bug的數據庫。因此,在上線之前所進行的各種深入且廣泛的數據庫測試,會大大減少部署到生產環境中所可能出現的故障數量和破壞程度。業界普遍認為:好的測試不是要去發現每一個bug,而是幫助您找到并修正大多數潛在的問題。
總結
眾所周知,數據庫的開發和設計是任何數據密集型項目的核心,它與各種業務應用都息息相關。因此,本文所列出的九種設計中的常見錯誤,都會在項目的推進和系統的運行中,對數據庫的后續性能產生嚴重的影響,進而產生高昂的修復成本。因此,我們應當在設計的一開始就盡量避開這些坑點,以構建出真正適合項目預期的數據庫。
原文標題:9 of the Most Common Mistakes in Database Design,作者:Mokhtar Ebrahim
【51CTO譯稿,合作站點轉載請注明原文譯者和出處為51CTO.com】