分享到

簡介

資料庫從不孤立存在。使用者、應用程式、指令碼,甚至其他資料庫都會向其輸入資訊並從中提取資訊,就像生物消耗和分配環境(以及彼此)的能量一樣。雖然沒有哪個資料庫能夠與地球的全球生態系統在規模或複雜性上相媲美,但設計和支援資訊系統仍然與照料小型生態系統(如花園、溫室或動物飼養箱)有許多相似之處。

經典的生態劃分也可應用於資料庫在資訊系統中的角色:動物、植物還是礦物?確定哪種模式適合給定的資料模型,需要儘可能地瞭解其所處的環境。

Animal, vegetable, and mineral modes

“動物”似乎描述了一種積極的組織原則,它嵌入(或者說,糾纏)在操作流程和工作流中,經過適應和程式設計——簡而言之,就是專業化。以“動物”方法構建的系統或子系統,若明確圍繞單一資料庫作為資訊流的收集器和單一真相來源,則表現出色。如果失去這種專注,“動物”型資料庫就有可能變成一隻大熊貓:行動遲緩、維護成本高昂,並帶來物流和官僚噩夢。

更“植物”型的資料庫只組織其獲取的資料,不多不少,它約束和提煉資訊,但不採取積極行動。這類資料庫用適應性換取了對工作流的集中控制和積極管理,它們收集和組織資訊,但不將行為和使用假設編碼進更嚴格的資料庫結構中。在資料庫並非唯一資訊處理場所,或有更大團隊和複雜溝通結構互動的系統中,處理一個較少程式設計的資料庫會更容易,因為它被視為 一種 而非 唯一的 組織原則。

還有一些“礦物”型資料庫設計甚至放棄了對資訊的最低限度管理許可權,僅提供最少結構的儲存,就像五千年前蘇美爾人刻寫賬簿和投訴的泥板一樣。有時確實只需要一個符合 ACID 原則的電子表格,但更仔細地審視系統是非常有必要的。此外,現有“礦物”型資料庫的實現可能未能考慮到或笨拙地近似於更復雜的資料模型,或者資料模型本身的一部分或全部不適合關係型表示。

多個數據庫

每個與資料庫互動的程式或系統——包括設計者、使用者或開發者——也都扮演著生態角色,它們消耗和生成資訊,進行組合、分離,或增添、消除細微差別,無論是好是壞。許多這些互動系統都有自己的資料模型,其中目標系統資料模型的一部分或全部現在構成了一個元件(有時透過眾所周知的模糊玻璃,正如任何曾詛咒過意外的VARCHAR(20)的人都能證明的那樣)。

這些連線意味著資料庫設計必須經常適應其他外部資料模型的至少一部分假設,即便不是其結構元素。資訊被拆分:使用者和預訂在一個數據庫中,酒店空房資訊來自另一個數據庫,航班預訂資訊儲存在航空公司,並在使用者和預訂端重複。模式變得糾纏不清,一個數據庫的更改會影響到其他資料庫。

管理更多事物及它們之間的更多互動總是更困難的,而將資料模型拆分到多個儲存尤其會產生深遠的影響。對完全關係模型的子部分進行封裝和處理,透過模式可以更安全地實現,所有主要的 RDBMS 都支援模式,除了 MySQL。但情況總在變化。有些資訊更適合非關係型結構。有些資訊已經分散在屬於其他系統的資料庫中,或者面向服務架構(宏觀或微觀)的採用使得分裂不可避免。更嚴格的彈性要求需要網路化、冗餘儲存。現在的資料模型比以往任何時候都更需要考慮到分佈在多個相互作用的資料儲存中。

拆分資料模型最重要的犧牲是引用完整性。在單個數據庫中,伺服器可以防止違反外部索引鍵約束的操作,例如插入或更新具有不存在父 ID 的記錄,或者刪除其他記錄所依賴的記錄。將資料模型的一部分移到另一個儲存中,維護正確性就成了你(和你的團隊)的問題。

專業解決方案

像其他任何事物一樣,引用完整性是一個可協商的約束,如果能獲得足夠的回報,犧牲它也是一種選擇。有時甚至都不是需要考慮的問題,如果資料模型在圖論意義上足夠簡單,實體很少,實體之間連線很少或主要是層次結構,或兩者兼而有之。效能和可擴充套件性要求也可以成為引入關係模型替代方案的理由,在這些情況下,資料模型的一部分以比 RDBMS 輕鬆容納的更高容量和更快流動的形式表示實際資訊。

21 世紀 00 年代後期,這些替代方案出現了寒武紀大爆發。突然之間,出現了儲存文件、圖、鍵值對的“NoSQL”資料庫。列式儲存透過將表橫向化並建模扁平、非規範化資料,實現了驚人的效能。新來者擁抱了跨網路伺服器的橫向擴充套件,拋棄了 ACID 規則,轉而青睞 BASE(“基本可用、軟狀態、最終一致性”),並開發了與 SQL 概念迥異的 API 和領域特定語言。不僅如此,圍繞資料儲存的討論重塑了資料庫作為概念的邊界。像 Kafka 這樣的流處理器是資料庫嗎?像 ElasticSearch 這樣的搜尋引擎呢?它們每個都從根本上促進了資訊的儲存和檢索;討論其中任何一個都需要呼叫大量的資料庫技術語言。更根本的是,它們每個都是特定型別資料建模問題的解決方案。

如果你需要儲存和處理...請考慮...
連線很少的層級結構、原始結構化文件或至少有一些共同欄位的物件文件資料庫 (Couchbase, MongoDB)
大量“扁平”資料,例如儀表讀數或結構化分析資料面向列的資料庫 (Cassandra, HBase),時序資料庫 (TimescaleDB, InfluxDB, Druid)
僅透過鍵標識和查詢的記錄鍵值儲存 (Redis, LevelDB),快取 (memcached)
記錄之間具有點對點導航的複雜關係圖資料庫 (OrientDB, Neo4j, TerminusDB)
按接收順序的瞬態資料流流處理器和佇列 (Kafka, RabbitMQ, ZeroMQ)
檔案。大量的檔案雲檔案儲存 (Google Cloud Storage, Amazon S3 and Athena)
非結構化文件,或模式高度可變的結構化文件搜尋引擎 (ElasticSearch, Solr),內容儲存庫 (Jackrabbit)
行星級規模的關係資料NewSQL 高度分散式關係資料庫 (VoltDB, Spanner)
以上至少幾種多模型資料庫 (FaunaDB, ArangoDB)

請注意,以上僅為示例,並非推薦!Kristof Kovacs 也維護著一份更詳細的總結,涵蓋了許多 NoSQL 選項,從流行到冷門。

預設選項

如果你不需要儲存至少數千兆位元組的、偏離關係資料模型的例外情況,你甚至可能不需要放棄 ACID 和引用完整性!關係型資料庫通常在全文搜尋和儲存結構化或非結構化文件方面表現出色;特別是 PostgreSQL 對 JSON 的處理非常廣泛,具有可索引的二進位制儲存和豐富的查詢工具集,使得混合關係-文件策略變得實用。Postgres 和其他 RDBMS 都透過伺服器元件、擴充套件或儲存引擎支援其他模型,其中一些專業儲存,如 TimescaleDB,是建立在關係型資料庫之上的。

因此,儘管幾十個營銷部門不遺餘力,古老的半世紀曆史的 RDBMS 仍然是首選的通用資料儲存,而非關係型解決方案則找到了適合其優勢的專業利基市場。NoSQL 資料庫可以完成其關係型對應物無法輕鬆或根本無法完成的各種任務,但關係型資料庫在可預見的未來仍將存在。透過伺服器調優、索引和表分割槽,單個關係型資料庫可以適應除最重負載之外的所有工作。即使這樣還不夠,還有複製功能。

複製與架構

深入探討複製技術超出了資料建模指南的範圍,但它們的使用確實會帶來不可忽視的後果。複製的資料庫不僅僅是變得更大:一旦資料儲存網路化,它就不再是整個系統架構中的單一元素。複製引入了一整套新的關注點,包括延遲、網路分割槽、維護等。

最常見的複製形式是僅將資料寫入單個伺服器。主伺服器將更改轉發給一個或多個副本伺服器,這些副本伺服器要麼在主伺服器宕機時待命替換它(故障轉移),要麼承擔響應讀取查詢的工作。在後一種情況下,網路延遲可能意味著更改不會立即可見,但由於它們只單向流動,因此仍能保證一致性。這種讀寫分離自然而然地適用於在適當的情況下在檢視中表示合併實體,特別是在軟體系統中,適用於命令查詢職責分離,這是一種有助於控制僅與檢索或儲存相關的複雜性的設計模式。

在另一種“多主”複製模式中,資料可以寫入和讀取多個伺服器,這些伺服器透過網路連線,在重負載下集體比單個伺服器更具彈性。然而,達成共識是複雜的,並且要實現更高水平的寫入驗證以保證永續性可能會很慢。這往往需要更簡單的資料模型和更精細地處理衝突和回滾。

大多數 NoSQL 資料儲存都是為叢集設計的,有些甚至到了在單臺計算機上執行幾乎是事後才考慮的地步。特別是,NoSQL 將分片(即從叢集中不同節點提供表分割槽)的概念推向了前沿。分片是這些資料庫實現規模的主要因素,但如果沒有複製,丟失一個節點仍然意味著丟失資料。大多數 NoSQL 資料庫提供基本複製,通常帶有自動故障轉移。少數資料庫,如 Cassandra 和 Couchbase,使用多個主節點。

CAP 定理

他的“CAP 定理”(一致性、可用性、分割槽容忍性:三選二)至今仍有共鳴,但就像動物/植物/礦物三元論一樣,它是一種優雅的過度簡化——不多不少。

Martin Kleppmann 在 2015 年詳細描述了 CAP 的缺點,這建立在 Coda Hale 早期澄清“三選二”方面的努力之上。Brewer 本人後來宣佈 Google 的 Spanner 資料庫“有效地達到 CA”,憑藉 Google 網路的巨大規模克服了 AP/CP 的二分法。

整合外部資訊

資訊很少僅在系統的資料庫和使用者之間流通。大多數資訊系統都是開放系統,資料從其他資訊系統流入,也流出到其他資訊系統。這些流通常適合自動化,並且在達到一定(並非非常大)的量時幾乎是強制性的;手動資料輸入是最後的手段。有時,外部資訊源是持續線上的,佇列、流處理器或專用守護程式會在記錄到達時新增它們,但從不同時處理太多。然而,其他時候,即時資料可能不可用,或者根本不必要——月銷售額或昨天的網站分析不需要精確到秒。

批次資料攝取過程通常被稱為 ETL,即提取-轉換-載入 (Extract-Transform-Load) 的縮寫,即使在沒有提取或轉換髮生的情況下,也非正式地如此稱呼。典型的 ETL 過程是一個 cron 作業或計劃任務,它從外部系統下載存檔的資料匯出,通常是像 CSV 或 TSV 這樣的扁平分隔格式。記錄可以在 ETL 任務將其寫入資料庫時進行轉換,或者,違反縮寫,之後進行批次轉換。批次轉換在涉及與現有資料連線時特別有用,因為資料庫可以一次性最佳化數千行的連線,比最佳化數千次單行連線更有效得多。

Integrating external information

資料匯入的第三方工具各不相同。專有 RDBMS 通常包含專門的 ETL 管理程式,例如 SQL Server Integration Services 或 Oracle Data Integrator,而主要的開源和 NoSQL 選項通常僅限於使用 mysqlimportmongoimport 等應用程式進行基本檔案載入,或在 PostgreSQL 和 Cassandra 中使用伺服器端 COPY 命令(Postgres 還在 psql 客戶端中提供客戶端 \copy 指令)。

然而,第三方 ETL 自動化正在成為一個可行的商業利基市場,尤其是在越來越多的資料庫託管在雲端的情況下。如果你有大量不同的傳入資料流或嚴格的合規性約束,那麼調查這些服務是值得的。它們做的任何事情你自己都可以用現有工具完成——問題在於你是否有時間自行實施和維護足夠健壯的 ETL 過程。

聯邦:統一資訊源

ETL 並非唯一的選擇。2003 年,SQL 標準引入了一個名為 SQL/MED 的擴充套件,意為外部資料管理。檔案、其他資料庫、其他關係型或非關係型 DBMS、REST 端點、目錄服務——所有這些以及更多都涉及看起來很像列和行的資料集,至少從正確的角度看是如此。任何看起來足夠像列和行的資料,都可以透過 SQL 進行查詢,如果不是完全管理的話。資料庫向用戶和其他外部系統呈現單一介面,同時將請求和更改路由到適當的目標。

在 IBM 的 DB2 首次實現後,其他資料庫用了數年時間才趕上 SQL/MED。目前,Oracle 支援將平面檔案作為“外部表”進行讀寫訪問,而 SQL Server 可以連線到“連結伺服器”,只要它們符合 Microsoft 的 OLEDB API。

真正有趣的事情正在開源 RDBMS 中發生。PostgreSQL 在 9.1 版本中引入了外部資料包裝器,並持續擴充套件其功能,而 MariaDB 的CONNECT 儲存引擎可以包裝大量資料來源。此外,Postgres 和 MariaDB 的實現都是可擴充套件的:如果你有現有包裝器無法處理的外部資料格式,你可以編寫自己的。Postgres 社群甚至開發了一個名為Multicorn 的 Python 框架,以簡化原本基於 C 語言的外部資料包裝器開發過程。

“聯邦”架構的理念源於區域政府和中央(聯邦)政府並存的雙重政府形式,與其他系統設計技術一樣,其目的是管理複雜性。各個子系統的使用者在其內部和與之協同工作;而那些只關心整體運作的人則與整體互動。就生態角色而言,這非常類似於資料庫操作的“動物”模式。聯邦資料庫是其所處系統的核心。它將資訊流吸引到自身並流經自身,建立連線,編碼對輔助模式的期望。但在這種“巨獸”能夠茁壯成長的資訊生態系統中,SQL/MED 是整合不同資料來源的強大工具。

關於作者
Dian Fay

Dian Fay

Dian 最初並沒有計劃輟學專攻 SQL 和後端開發,但事情就這樣發生了。十五年後,她設計了支援從工業物流和追溯系統到擁有數百萬使用者的社交媒體遊戲等各種資料庫。她是 MassiveJS 的當前維護者,這是一個專注於充分利用 PostgreSQL 的 Node.js 開源資料對映器。
© . This site is unofficial and not affiliated with Prisma Data, Inc.