分享至

簡介

資料庫相對於其他更簡單的資料儲存選項的主要優勢之一是它們能夠以有序、易於查詢的結構儲存資訊。這些特性源於資料庫實現 Schema 來描述它們儲存的資料。

一個 資料庫 Schema 充當資料庫中資料形狀和格式的藍圖。對於關係型資料庫,這包括透過表、主鍵、資料型別、索引和其他物件描述資料類別及其連線。對於 NoSQL Schema,這通常涉及根據最重要的預期查詢模式組織資料。

無論哪種情況,瞭解資料庫 Schema 的價值以及如何根據您的需求最佳地設計和最佳化它都至關重要。本指南將重點介紹什麼是資料庫 Schema、您可能遇到的不同 Schema 型別、它們為何重要以及在設計自己的 Schema 時應牢記哪些事項。

為什麼資料庫 Schema 很重要?

資料庫 Schema 很重要,原因有很多。

無論資料來源或應用如何,您的資料幾乎總是包含一些規律性。有些資料高度規律,這意味著它們都可以用相同的模式來描述。有些資料則更不規律,但即便如此,其元資料(關於資料本身的上下文資料)通常仍然是規律的。

資料庫 Schema 告訴資料庫您的資料是什麼以及如何處理它。資料庫 Schema 幫助資料庫引擎理解這些模式,從而使其能夠對資料強制執行約束、在查詢時響應正確的資訊,並以使用者請求的方式對其進行操作。

良好的 Schema 傾向於減少隱式資訊,轉而使其對系統及其使用者可見。關係型資料庫中的 Schema 可以減少資訊冗餘,確保資料一致性,並提供訪問和連線相關資料所需的腳手架和結構。在非關係型上下文中,良好的 Schema 透過將儲存格式與對應用程式至關重要的訪問模式對齊,從而實現高效能和可伸縮性。

定義物理 Schema 與邏輯 Schema

在我們深入之前,我們應該介紹一些定義。兩個可能令人困惑的術語是物理 Schema邏輯 Schema。這兩個術語根據其使用的上下文可以傳達不同的含義。

就本文而言,我們主要討論設計資料庫 Schema 時的邏輯 Schema 和物理 Schema。

設計資料庫 Schema 時

在談論設計資料庫 Schema 時,一個 邏輯 Schema 是一種將資料組織成不同類別、定義資料屬性並確定資料庫專案最佳結構的通用設計。此通用文件不包含實現細節,因此與平臺無關。它可以作為藍圖並在各種資料庫系統中實現。

在相同的上下文中,一個 物理 Schema 被認為是設計過程中的下一步,其中解決了特定於實現的細節。不同實體、約束、鍵、索引和其他項的名稱被識別並對映到邏輯 Schema。這為使用給定資料庫平臺進行實現提供了具體的計劃。

在此上下文中,邏輯 Schema 和物理 Schema 是設計過程的不同階段。該過程的目標是根據一組需求迭代地開發實施計劃,首先闡述資料的抽象特性,然後將該組織對映到您想要使用的資料庫系統的工具集和語言。

討論資料庫架構時

物理 Schema 和邏輯 Schema 有時在資料庫中出現的另一個上下文是實際資料庫軟體的物理和虛擬架構。

在此上下文中,邏輯 Schema 指的是使用者與之互動的可見資料庫實體。這意味著表、鍵、檢視和索引等物件是使用者使用資料庫軟體建立和操作的抽象。這些專案在系統中的佈局是資料庫呈現的邏輯 Schema 的一部分。

在相同的上下文中,物理 Schema 指的是資料庫軟體在與檔案系統互動時處理資料、檔案和儲存的方式。例如,資料庫架構的物理 Schema 可以決定系統是為每個資料庫還是每個表儲存單獨的檔案,並決定如何將這些檔案分割槽到多個伺服器上。

靜態 Schema 與動態 Schema

另一種重要的分類可以幫助澄清關係型資料庫和非關係型資料庫中 Schema 之間的差異,即靜態 Schema 和動態 Schema 之間的差異。

靜態 Schema 是通常與關係型資料庫關聯的 Schema 型別。它們預先定義為資料必須遵循的形狀,才能被系統接受。當使用靜態 Schema 時,資料庫系統能夠強制執行這些模式,因為靜態 Schema 是資料庫系統可以根據輸入進行驗證的期望狀態的斷言。

相反,動態 Schema 在非關係型上下文中更為普遍。動態 Schema 的靈活性更高,可能缺乏任何預先構思的組織結構。相反,動態 Schema 是根據輸入到系統中的資料特性演變而來的。雖然許多非關係型資料庫可以儲存具有任意內部結構的資訊,但在大多數實際用例中,通常會出現規律的模式。

由於動態 Schema 是演變而來的結構,資料庫系統不能將其用作一致性工具。然而,作為使用者,理解並圍繞它們進行開發仍然至關重要。從總體上理解您的資料將是什麼樣子,以及您的應用程式將如何與它互動,將幫助您選擇滿足您的需求、效能良好並避免不必要不一致的結構。

設計資料庫 Schema

現在您已經瞭解了不同型別的資料庫 Schema,那麼如何為您的專案設計一個呢?設計有效的 Schema 需要思考和實踐,以及對問題域和將使用資料的系統有透徹的理解。

設計過程因您設計的資料庫型別而異。具體來說,靜態 Schema 的設計過程與動態 Schema 的設計過程不同。實際上,這些差異最終與關係型資料庫(靜態)和非關係型資料庫(動態)的設計差異相一致。

一般提示

儘管關係型資料庫和非關係型資料庫的 Schema 設計存在差異,但有一些通用提示適用於任何 Schema 開發。由於其中許多對設計過程的開始很重要,因此有必要先討論這些。

瞭解您的資料

設計 Schema 的第一步應該始終是瞭解您的資料和領域。如果不瞭解資料庫將管理的資訊及其使用環境,就不可能開發出良好的資料庫設計。

儘管您一開始可能不會了解所有資料特性,但儘可能多地瞭解系統預期管理的資料對於設計至關重要。

您應該嘗試回答的一些問題包括

  • 廣義上講,資料會是什麼?
  • 哪些屬性是重要的,需要記錄?
  • 您的總資料集會有多大?
  • 系統積累新資料的速度會有多快?
  • 您的資料會高度規律嗎?

瞭解使用模式

同樣,不瞭解使用者需求就設計資料庫 Schema,就像其他軟體設計一樣,會帶來問題。如果您不是資料使用領域的專家,則需要諮詢相關人士來指導您瞭解需求。

您應該問自己以下問題:

  • 最常見的查詢可預測嗎?
  • 將會有多少併發使用者或客戶端?
  • 典型操作和查詢會觸及多少資料?
  • 大多數請求是讀查詢還是寫查詢?
  • 哪些資料會定期一起查詢?
  • 大多數操作是針對單個記錄還是聚合多條記錄?

制定命名約定

儘管這看起來可能不重要,但設計一套命名約定並嚴格遵循它將有助於開發和日常使用。

命名和樣式約定有助於最大限度地減少在命名新實體時需要進行的腦力勞動。同樣,約定允許使用者在訪問 Schema 中不同專案時安全地假定一種模式。某些資料庫系統或資料庫型別已經有流行的命名約定,您可以遵循這些約定以避免意外,並避免需要開發自己的標準。

您可能需要考慮的一些樣式和命名約定:

  • 對於區分大小寫的系統,您應該如何使用大寫和小寫字母?
  • 專案何時應使用單詞的複數形式,何時應使用單數形式?
  • 多詞名稱應該用下劃線、破折號還是其他分隔符分隔單詞?
  • 應該總是使用全名,還是在某些情況下允許使用縮寫?

為關係型資料庫設計 Schema

關係型資料庫通常被認為是靈活的通用解決方案。它們處理即席查詢的能力使得同一個資料庫可以服務於不同的應用程式和用例。因此,在為關係型資料庫設計 Schema 時,您的最終目標通常是以一種促進靈活性同時最大限度地減少資料不一致進入系統的機會的方式來表示您的資料。

開發邏輯 Schema

關係型 Schema 設計通常從邏輯 Schema 開始,如上一節所述。

您需要規劃要管理的資料項、它們之間的關係以及需要考慮的任何重要屬性,而無需考慮實現細節或效能標準。這一步很重要,因為它將您的所有資料項收集在一個地方,並允許您在抽象層面上理清它們之間的關係。

您可以開始草繪表示特定資料項及其屬性的表。這種對映過程通常最好透過實體關係(或 ER)模型來表示。ER 模型是透過定義專案型別及其屬性,然後連線這些來對映關係和依賴項的圖表,以直觀地表示資料物件。

ER 模型經常用於早期 Schema 設計,因為它們非常擅長幫助您弄清楚您擁有哪些不同的實體、必須管理哪些屬性、哪些實體相互關聯以及它們關係的具體性質。使用 ER 模型圖來表示您的邏輯 Schema 可以為您提供一個堅實的計劃,說明您希望您的資料庫設計是什麼樣子,而無需評論特定於實現的細節。

開發物理 Schema

一旦您有了邏輯 Schema,下一步就是透過建立物理 Schema 來確定具體的實現細節(如上一節所述)。物理 Schema 將精確地決定您希望如何使用可用的資料庫結構和功能來提交您的計劃。

第一步通常是遍歷每個資料庫實體並確定其主鍵欄位。主鍵用於唯一標識表中的每條記錄,以及將不同表中的記錄繫結在一起。當邏輯 Schema 中存在兩個實體之間的關係時,您需要在物理 Schema 中透過將一個表中的主鍵作為另一個表中的外部索引鍵來引用,從而連線這兩個表。這種關係的方向將影響您在使用資料庫時連線不同實體的效能和便捷性。

在此階段您還需要考慮的另一個問題是預測的查詢模式。這些表中的某些表和欄位的訪問頻率將遠高於其他表和欄位。這些“熱點”是資料庫索引的良好候選。資料庫索引顯著加快了常用專案的檢索速度,但代價是資料更新期間效能會變差。確定最初要索引哪些列將幫助您平衡這些考慮因素,並定義系統中索引最關鍵的位置。

規範化您的資料結構

在此過程中,您可能會發現將邏輯實體中的某些元素提取到其自己的獨立表中會更容易。例如,您可能希望從客戶中提取送貨地址,以便多個送貨地址可以與單個客戶關聯,並且產品訂單可以引用特定地址。這些更改可以被認為是稱為正規化化的過程的一部分。

資料庫正規化化是一個確保您的資料庫僅表示每條資料一次且不允許導致不一致的更新的過程。正規化化是一個巨大的話題,在很大程度上超出了本指南的範圍,但物理 Schema 設計過程的一部分涉及確定要追求的正規化化級別,並根據需要轉換資料實體以實現該目標。

為非關係型和 NoSQL 資料庫設計 Schema

非關係型資料庫的設計過程通常大相徑庭。這種差異很大程度上源於非關係型資料庫通常被選擇是為了在有限數量的預定義查詢上實現高效能。

確定您的主要查詢

非關係型資料庫的 Schema 通常與將使用它們的應用程式協同設計。Schema 反映了應用程式的特定需求,從某種意義上說,它是一種定製結構,旨在適應應用程式開發的模式。

由於這種密切關係,確定您的資料庫必須最佳化以響應哪些查詢非常重要。第一步是弄清楚您的資料庫需要執行哪些查詢。由於您還沒有資料結構,這些將是偽查詢,但瞭解您的應用程式需要哪些資料才能執行某些操作是您的首要目標。

一旦您對應用程式需要執行的查詢有了很好的瞭解,您就需要選擇最重要的查詢進行關注。這些是您的應用程式經常執行且不能等待的查詢。

確定哪些查詢最重要,可以告訴您資料結構需要最佳化的確切訪問模式。資料庫系統儲存和表示資料的方式將對其快速檢索和操作資料項的能力產生巨大影響。

圍繞您的主要查詢設計初始 Schema

現在您已經瞭解了最基本的訪問模式,您就可以開始開發與這些查詢相匹配的 Schema。

此過程的第一步是確定每個查詢需要返回的精確資訊。然後,規劃將所有資訊儲存在單個實體中以響應查詢的樣子。

例如,如果您的應用程式將查詢資料庫以檢索使用者個人資料資訊,您的起點很可能是假設所有使用者個人資料資訊都可以儲存在一個位置。

儘可能合併和去重資料實體

確定了所需的屬性並規劃了將與每個查詢相關的所有專案儲存在單個實體中的樣子後,檢查是否存在重疊。這樣做的目的是儘可能整合資料實體,以減少系統需要維護的獨立專案數量。您維護的獨立實體型別越多,出現不一致和更新效能問題的可能性就越大。

其中一些重疊會相當明顯。一個查詢返回的屬性是另一個查詢屬性的子集的情況可以安全地合併到單個實體中。

其他時候,確定如何對映查詢資訊可能更困難。非關係型資料庫通常不擅長在單個查詢中合併來自多個實體的資料,而關係型資料庫透過聯接在此方面表現出色。因此,當某些屬性或實體存在於多個查詢中時,您可能需要選擇最佳的資料表示方式。

確定您的應用程式可以在何處填補空白

對於某些查詢,您的應用程式可能需要承擔部分資料組裝工作,而不是依賴資料庫在單個查詢中響應所有相關資訊。例如,如果您需要處理客戶資訊及其相關訂單,將訂單儲存在不同的類別中並在客戶物件中透過 ID 引用它們可能更合理。

某些資料庫系統無法透過遵循物件之間的引用輕鬆連線此資訊。相反,您的應用程式可能需要首先查詢客戶,然後使用您發現的訂單 ID 對每個相關訂單進行額外查詢。

在您的應用程式程式碼中執行這些操作有助於規避某些非關係型資料庫的限制。這通常是比試圖在單個條目中維護大量資訊或試圖為許多不同型別的資料庫物件多次複製資料更好的選擇。這些選項可能會導致非常差的效能和資料一致性。

話雖如此,一旦應用程式程式碼和資料庫 Schema 都上線,測試和調優它們將非常重要,以確保您不會為了快速的資料庫操作而犧牲良好的應用程式效能。一個好的經驗法則是儘可能利用資料庫的功能,因為它們針對資訊檢索和操作進行了高度最佳化,並根據需要在應用程式中進行補充。

確定合適的分割槽鍵

對於高度可擴充套件的非關係型資料庫,使用者通常需要確定分割槽或分片鍵。這些鍵將用於在不同伺服器之間拆分資料集,以提高效能和響應能力。

找到合適的分割槽鍵高度依賴於您的資料和工作負載。然而,一些通用規則可以為您提供指導。

最好嘗試選擇具有相當均勻的鍵分佈的分割槽鍵。例如,如果您需要分發客戶資料,他們的出生月份通常會導致不錯的分佈。相反,如果您正在銷售冬季服裝,註冊月份就不會是一個好的分割槽鍵,因為您的產品的季節性可能會影響鍵的分佈。對候選資料應用雜湊演算法有時也有助於更均勻地分佈您的鍵空間。

另一個考慮因素是您的工作負載是讀密集型還是寫密集型。如果您的應用程式是讀密集型的,您可能希望選擇一個分割槽鍵,該鍵允許您將盡可能多的相關資料寫入單個伺服器。這將有助於您避免每次需要檢索相關資料時都必須從多個伺服器讀取。

另一方面,如果您的工作負載是寫密集型的,通常更傾向於將寫入分散到儘可能多的伺服器上。如果每個請求最終都將資料寫入同一臺伺服器,那麼您將不會在寫密集型操作中獲得太多效能提升。

總結

設計有效的資料庫 Schema 需要耐心、實踐,並且通常需要大量的試錯。

首先,您必須嘗試很好地瞭解您的資料將是什麼樣子、您的應用程式將如何使用它以及需要哪些可用性和資料完整性要求。之後,您的目標是開發一個能夠反映您的資料特定特徵並促進您預期的用例型別的 Schema。

Schema 設計與其他任何型別的設計一樣,是一個迭代過程。隨著您對問題域理解的加深以及實際效能資料的可用,預計會更改您的設計。雖然您可能需要隨著時間的推移不斷發展您的 Schema,但從堅實的基礎開始將有助於此過程,並降低未來發生重大、破壞性 Schema 更改的可能性。

關於作者
Justin Ellingwood

Justin Ellingwood

Justin 自 2013 年以來一直撰寫有關資料庫、Linux、基礎設施和開發者工具的文章。他目前與妻子和兩隻兔子住在柏林。他通常不必用第三人稱寫作,這對所有相關方來說都是一種解脫。
© . This site is unofficial and not affiliated with Prisma Data, Inc.