數據庫設計中的不良做法:您是否犯了這些錯誤?
已發表: 2022-03-11每當您作為開發人員被賦予基於現有代碼的任務時,您都必鬚麵對許多挑戰。 其中一項挑戰——通常是最苛刻的挑戰——涉及理解應用程序的數據模型。
您通常會遇到令人困惑的表、視圖、列、值、存儲過程、函數、約束和触發器,這些需要很長時間才能理解。 而且,一旦他們這樣做了,您就會開始注意到許多改進和利用存儲信息的方法。
如果您是一位經驗豐富的開發人員,您很可能還會注意到一開始可以做得更好的事情,即設計缺陷。
在本文中,您將了解一些常見的數據庫設計不良做法,它們為什麼不好,以及如何避免它們。
不良做法 1:忽略數據的用途
存儲數據以供以後使用,目標始終是以最有效的方式存儲和檢索數據。 為了實現這一點,數據庫設計者必須提前知道數據將代表什麼,如何獲取數據以及以什麼速率獲取數據,其操作量將是多少(即預期有多少數據),最後,它將如何使用。
例如,每天手動收集數據的工業信息系統與實時生成信息的工業系統具有不同的數據模型。 為什麼? 因為與在同一時期管理數百萬條記錄相比,每月處理數百或數千條記錄是非常不同的。 如果數據量很大,設計人員必須特別考慮以保持數據庫的效率和可用性。
但是,當然,數據量並不是唯一需要考慮的方面,因為數據的用途也會影響規範化水平、數據結構、記錄大小以及整個系統的總體實現。
因此,徹底了解您將創建的數據系統的用途會導致在選擇數據庫引擎、要設計的實體、記錄大小和格式以及數據庫引擎管理策略方面考慮。
忽略這些目標將導致設計在其基礎上存在缺陷,儘管在結構和數學上是正確的。
不良做法 2:標準化不良
設計數據庫不是一項確定性的任務。 兩個數據庫設計者可能會遵循給定問題的所有規則和規範化原則,並且在大多數情況下,他們會生成不同的數據佈局。 這是軟件工程的創造性本質所固有的。 但是,有一些分析技術在每種情況下都有意義,遵循它們是獲得性能最佳的數據庫的最佳方式。
儘管如此,我們經常會遇到不遵循最基本的規範化規則而動態設計的數據庫。 我們必須明確一點:每個數據庫至少應該規範化為第三範式,因為它是最能代表您的實體的佈局,並且其性能將在查詢和插入-更新-刪除記錄之間得到最佳平衡.
如果您偶然發現不符合 3NF、2NF 甚至 1NF 的表格,請考慮重新設計這些表格。 您為此付出的努力將在短期內得到回報。
不良做法 3:冗餘
與前一點非常相關,因為規範化的目標之一是減少它,冗餘是另一種經常出現的不好的做法。
冗餘字段和表對開發人員來說是一場噩夢,因為它們需要業務邏輯來保持相同信息的多個版本是最新的。 如果徹底遵循規範化規則,這是可以避免的開銷。 儘管有時冗餘似乎是必要的,但它必須僅在非常特殊的情況下使用,並清楚地記錄在案,以便在未來的開發中考慮。
冗餘的典型不良影響是不必要地增加數據庫大小、數據容易出現不一致以及數據庫效率降低,但更重要的是,它可能導致數據損壞。
不良做法 4:不良的參照完整性(約束)
參照完整性是數據庫引擎為保持最佳數據質量而提供的最有價值的工具之一。 如果在設計階段沒有實現約束或約束很少,數據完整性將不得不完全依賴於業務邏輯,從而容易受到人為錯誤的影響。
錯誤做法 5:不利用數據庫引擎功能
當您使用數據庫引擎 (DBE) 時,您將擁有一個功能強大的軟件來處理您的數據處理任務,這將簡化軟件開發並保證信息始終正確、安全和可用。 DBE 提供以下服務:
- 提供快速有效的數據查看方式的視圖,通常為查詢目的對其進行反規範化,而不會丟失數據的正確性。
- 有助於加快對錶的查詢的索引。
- 無需編程即可幫助分析信息的聚合函數。
- 如果發生意外情況,將全部執行並提交或取消(回滾)的事務或數據更改語句塊,從而使信息始終處於正確狀態。
- 在執行事務時保持數據安全和正確的鎖。
- 提供編程功能以允許執行複雜數據管理任務的存儲過程。
- 允許複雜計算和數據轉換的函數。
- 有助於保證數據正確性和避免錯誤的約束。
- 當數據上發生事件時有助於自動執行操作的觸發器。
- 在後台運行的命令優化器(執行計劃器),確保每個句子都以最佳狀態執行,並為將來的情況保留執行計劃。 這是使用視圖、存儲過程和函數的最佳理由之一,因為它們的執行計劃永久保存在 DBE 中。
不了解或忽略這些功能將使開發走上一條極其不確定的道路,並且肯定會導致錯誤和未來的問題。

不良做法 6:複合主鍵
這是一個有爭議的觀點,因為現在許多數據庫設計人員都在談論使用整數 ID 自動生成的字段作為主鍵,而不是由兩個或多個字段組合定義的複合字段。 這目前被定義為“最佳實踐”,我個人傾向於同意它。
然而,這只是一個約定,當然,DBE 允許定義復合主鍵,許多設計者認為這是不可避免的。 因此,與冗餘一樣,複合主鍵是一種設計決策。
但是請注意,如果您的具有復合主鍵的表預計會有數百萬行,則控制複合鍵的索引可能會增長到 CRUD 操作性能非常下降的程度。 在這種情況下,最好使用一個簡單的整數 ID 主鍵,其索引將足夠緊湊,並建立必要的 DBE 約束以保持唯一性。
錯誤做法 7:索引不佳
有時,您將擁有一個需要按多列查詢的表。 隨著表的增長,您會注意到這些列上的 SELECT 速度變慢。 如果表足夠大,從邏輯上講,您會認為在用於訪問該表的每一列上創建一個索引,但幾乎立即發現 SELECT 的性能有所提高,但 INSERT、UPDATE 和 DELETE 的性能下降了。 這當然是因為索引必須與表保持同步,這意味著 DBE 的大量開銷。 這是一個典型的過度索引情況,您可以通過多種方式解決; 例如,在與用於查詢表的主鍵不同的所有列上只有一個索引,將這些列從最常用到最少排序可能在所有 CRUD 操作中提供比每列一個索引更好的性能。
另一方面,眾所周知,在用於查詢的列上沒有索引的表將導致 SELECT 的性能不佳。
此外,索引效率有時取決於列類型; INT 列上的索引顯示出可能的最佳性能,但 VARCHAR、DATE 或 DECIMAL(如果有意義的話)上的索引效率不高。 這種考慮甚至會導致重新設計需要以盡可能高的效率訪問的表。
因此,索引總是一個微妙的決定,太多的索引可能和太少一樣糟糕,因為要索引的列的數據類型對最終結果有很大的影響。
不良做法 8:糟糕的命名約定
這是程序員在面對現有數據庫時經常遇到的問題:通過表和列的名稱了解其中存儲了哪些信息,因為通常沒有其他方法。
表名必須描述它包含的實體,每個列名必須描述它代表的信息。 這很容易,但是當表必須相互關聯時,它就開始變得複雜了。 名稱開始變得混亂,更糟糕的是,如果命名約定與不合邏輯的規範混淆(例如,“列名必須為 8 個字符或更少”)。 最後的後果是數據庫變得不可讀。
因此,如果期望數據庫能夠持續並隨著它支持的應用程序而發展,那麼命名約定總是必要的,這裡有一些指導方針來建立一個簡潔、簡單和可讀的命名約定:
- 對錶名或列名大小沒有限制。 最好有一個描述性的名稱,而不是一個沒人記得或理解的首字母縮寫詞。
- 相同的名稱具有相同的含義。 避免具有相同名稱但具有不同類型或含義的字段; 這遲早會令人困惑。
- 除非必要,否則不要多餘。 例如,在“Item”表中,不需要有“ItemName”、“PriceOfItem”或類似名稱的列; “名稱”和“價格”就足夠了。
- 當心 DBE 保留字。 如果要將列稱為“索引”,這是一個 SQL 保留字,請嘗試使用不同的名稱,例如“IndexNumber”。
- 如果堅持簡單的主鍵規則(自動生成單個整數),請在每個表中將其命名為“Id”。
- 如果連接到另一個表,將必要的外鍵定義為一個整數,命名為“Id”,後跟連接表的名稱(例如,IdItem)。
- 如果命名約束,請使用描述約束的前綴(例如,“PK”或“FK”),後跟所涉及的一個或多個表的名稱。 當然,謹慎使用下劃線(“_”)有助於提高可讀性。
- 要命名索引,請使用前綴“IDX”,後跟表名和索引的列。 此外,如果索引是唯一的,則使用“UNIQUE”作為前綴或後綴,並在必要時使用下劃線。
互聯網上有許多數據庫命名指南,它們將更加清楚地說明數據庫設計的這一非常重要的方面,但有了這些基本的,你至少可以得到一個可讀的數據庫。 這裡重要的不是您的命名准則的大小或複雜性,而是您遵循它們的一致性!
一些最後的評論
數據庫設計是知識和經驗的結合; 自早期以來,軟件行業已經發展了很多。 幸運的是,有足夠的知識可以幫助數據庫設計人員獲得最佳結果。
互聯網上有很好的數據庫設計指南,也有數據庫設計中要避免的不良做法和事情。 只需選擇並堅持下去。
而且,別忘了,只有通過實驗、錯誤和成功,你才能學到東西,所以現在就開始吧。