11 條重要的數據庫設計規則

jopen 10年前發布 | 11K 次閱讀 數據庫設計

我之所以寫下這篇長文是因為,很多開發者一參與到數據庫設計,就會很自然地把“三范式”當作銀彈一樣來使用。他們往往認為遵循這個規范就是數據庫設計的唯一標準。由于這種心態,他們往往盡管一路碰壁也會堅持把項目做下去。

如果你對 “三范式” 不清楚,請 點擊這里一步一步的了解什么是“三范式”。

大家都說標準規范是重要的指導方針,并且也都這么做,但是死記硬背還是會帶來麻煩的。以下11點是我在數據庫設計時會優先考慮的規則。

規則1:弄清楚將要開發的應用程序是什么性質的(OLTP 還是 OLAP)?

當你要開始設計一個數據庫的時候, 你應該首先要分析出你為之設計的應用程序是什么類型的,它是“事務處理型” (Transactional)的還是 “分析型” (Analytical)的?你會發現許多開發人員采用標準化做法去設計數據庫,而不考慮目標程序是什么類型的。采用這種做法設計的數據庫很快就會陷入性 能、客戶定制化的問題當中。正如前面所說的,這里有兩種應用程序類型,“基于事務處理” 和 “基于分析”,下面讓我們來了解一下這兩種類型究竟說的是什么意思:

  • 事務處理型:對于這種類型的應用程序,你的用戶更關注數據的增查改刪(CRUD,Creating/Reading/Updating/Deleting)。這種類型官方稱之為 “OLTP”。
  • 分析型:對于這種類型的應用程序,你的用戶更關注數據分析、報表、趨勢預測等功能。這一類的數據庫的“插入” 和“更新”操作相對來說是比較少的。用戶的主要目的是更加快速地查詢、分析數據。這種類型官方稱之為 “OLAP”。
  • </ul>

    11 條重要的數據庫設計規則

    那么換句話說, 如果你認為插入、更新、刪除數據這些操作在你的程序中更為突出的話,那就設計一個規范化的表,否則的話就去創建一個扁平的、不規范化的數據庫結構

    以下這個簡單的圖表顯示了像左邊 Names 和 Address這樣的簡單規范化的表,怎么通過應用不規范化結構來創建一個扁平的表結構。

    11 條重要的數據庫設計規則

    規則2:將你的數據按照邏輯意義分成不同的塊,讓事情做起來更簡單

    這個規則其實就是 “三范式”中的第一范式。違反這條規則的一個標志就是: 你的查詢使用了很多字符串解析函數,例如 substring、charindex 等等。若真如此,那就需要應用這條規則了。

    比如你看到的下面圖片中有一個有學生名字的表,如果你想要查詢學生名字中包含“Koirala”,但不包含“Harisingh”的記錄,你可以想象一下你將會得到什么樣的結果。

    所以更好的做法是將這個字段拆分為更深層次的邏輯分塊,以便我們的表數據寫起來更干凈,以及優化查詢。

    11 條重要的數據庫設計規則

    規則3:不要過度使用“規則 2”

    開發者都是一個很可愛的群體。如果你告訴他們這是一條解決問題的正路,他們就會一直這么做下去,做到過了頭導致產生一些不必要的后果。這也可以應用于我們 剛剛在前面提到的規則2。當你考慮字段分解時,先暫停一下,并且問問你自己是否真的需要這么做。正如前面所說的,分解應該是要符合邏輯的。

    例如,你可以看到電話號碼這個字段,你很少會把電話號碼的 ISD 代碼單獨分開來操作(除非你的應用程序要求這么做)。所以一個很明智的決定就是讓它保持原樣,否則這會帶來更多的問題。

    11 條重要的數據庫設計規則

    規則4:把重復、不統一的數據當成你最大的敵人來對待

    集中那些重復的數據然后重構它們。 我個人更加擔心的是這些重復數據帶來的混亂而不是它們占用了多少磁盤空間

    例如下面這個圖表,你可以看到 "5th Standard" 和 "Fifth standard" 是一樣的意思,它們是重復數據。現在你可能會說是由于那些錄入者錄入了這些重復的數據或者是差勁的驗證程序沒有攔住,讓這些重復的數據進入到了你的系統。 現在,如果你想導出一份將原本在用戶眼里十分困惑的數據顯示為不同實體數據的報告,該怎么做呢?

    11 條重要的數據庫設計規則

    解決方法之一是將這些數據完整地移到另外一個主表,然后通過外鍵引用過來。在下面這個圖表中你可以看到我們是如何創建一個名為Standards 的主表,然后同樣地使用簡單的外鍵連接過去。

    11 條重要的數據庫設計規則

    規則5:當心被分隔符分割的數據,它們違反了“字段不可再分”規則

    前面的規則 2 即“第一范式”說的是避免“重復組”。下面這個圖表作為其中的一個例子解釋了“重復組”是什么樣子的。如果你仔細的觀察 Syllabus 這個字段,會發現在這一個字段里實在是填充了太多的數據了。像這些字段就被稱為“重復組”了。如果我們又得必須使用這些數據,那么這些查詢將會十分復雜并 且我也懷疑這些查詢會有性能問題。

    11 條重要的數據庫設計規則

    這些被塞滿了分隔符的數據列需要特別注意。一個較好的辦法是將這些字段移到另外一個表中,使用外鍵連接過去,以便于更好的管理。

    11 條重要的數據庫設計規則

    那么,讓我們現在就應用規則2(第一范式)“避免重復組” 吧。你可以看到上面這個圖表,我創建了一個單獨的 Syllabus表,然后使用“多對多” 關系將它與 Subject表關聯起來。

    通過這個方法,主表(Student 表)的 Syllabus字段就不再有重復數據和分隔符了。

    規則6:當心那些僅僅部分依賴主鍵的列

    11 條重要的數據庫設計規則

    留心注意那些僅僅部分依賴主鍵的列。例如上面這個圖表,我們可以看到這個表的主鍵是 Roll No.+Standard。現在請仔細觀察 Syllabus 字段,可以看到 Syllabus字段僅僅關聯Standard字段而不是直接地關聯某個學生Roll No.字段。

    Syllabus 字段關聯的是學生正在學習的哪個課程級別字段而不是直接關聯到學生本身。那如果明天我們要更新教學大綱(課程)的話還要痛苦地為每個同學也修改一下,這明顯是不符合邏輯的(也是不正常的做法)。 更有意義的做法是將這些字段從這個表移到另外一個表,然后將它們與 Standard表關聯起來

    你可以看到我們是如何移動 Syllabus 字段并且同樣地附上 Standard 表。

    這條規則只不過是 “三范式” 里的 “第二范式”:“ 所有字段都必須完整地依賴主鍵而不是部分依賴”。

    規則7:仔細地選擇派生列

    11 條重要的數據庫設計規則

    如果你正在開發一個 OLTP型的應用程序,那強制不去使用派生字段會是一個很好的思路,除非有迫切的性能要求,比如經常需要求和、計算的 OLAP 程序,為了性能,這些派生字段就有必要存在了。

    通過上面的這個圖表,你可以看到 Average 字段是如何依賴 Marks 和 Subjects 字段的。這也是冗余的一種形式。 因此對于這樣的由其他字段得到的字段,需要思考一下它們是否真的有必要存在

    這個規則也被稱為 “三范式” 里的第三條:“ 不應該有依賴于非主鍵的列” 。 我的個人看法是不要盲目地運用這條規則,應該要看實際情況,冗余數據并不總是壞的。如果冗余數據是計算出來的,看看實際情況再來決定是否應用這第三范式。

    規則8:如果性能是關鍵,不要固執地去避免冗余

    11 條重要的數據庫設計規則

    不要把“避免冗余”當作是一條絕對的規則去遵循。如果對性能有迫切的需求,考慮一下打破常規。常規情況下你需要做多個表的連接操作,而在非常規的情況下這樣的多表連接是會大大地降低性能的。

    規則9:多維數據是各種不同數據的聚合

    OLAP 項目主要是解決多維數據問題
    。比如你可以看看下面這個圖表,你會想拿到每個國家、每個顧客、每段時期的銷售額情況。簡單的說你正在看的銷售額數據包含了三個維度的交叉。

    11 條重要的數據庫設計規則

    為這種情況做一個實際的設計是一個更好的辦法。簡單的說,你可以創建一個簡單的主要銷售表,它包含了銷售額字段,通過外鍵將其他所有不同維度的表連接起來。

    11 條重要的數據庫設計規則

    11 條重要的數據庫設計規則

    規則10:將那些鍵/值表統一起來設計

    很多次我都遇到過這種鍵/值表。鍵/值表意味著它有一些鍵,這些鍵被其他數據關聯著。比如下面這個圖表,你可以看到我們有 Currency和 Country這兩張表。如果你仔細觀察你會發現實際上這些表都只有鍵和值。

    11 條重要的數據庫設計規則

    對于這種表,創建一個主要的表,通過一個 Type字段來區分不同的數據將會更有意義。

    規則11:無限分級結構的數據,引用自己的主鍵作為外鍵

    我們會經常碰到一些無限分級結構的數據。例如考慮一個多級銷售方案的情況,一個銷售人員之下可以有多個銷售人員。注意到都是“銷售人員”。也就是說數據本身就是一個層級。但是層級不同。 這時候我們可以引用自己的主鍵作為外鍵來表達這種層級關系,從而達成目的。

    11 條重要的數據庫設計規則

    這篇文章的用意 不是叫大家不要遵循范式,而是叫大家不要盲目地遵循范式。根據你的項目性質和需要處理的數據類型來做出正確的選擇。

    11 條重要的數據庫設計規則
 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!