數據模型與查詢語言 ------《Designing Data-Intensive Applications》讀書筆記2


數據模型是開發軟件的最重要的部分,因為它們對應用程序有着深遠的影響:不僅是軟件的編寫方式,而且也影響我們如何解決的問題的方式。第二篇讀書筆記,我們聊一聊數據模型的設計。

1.數據模型的分層

作為一個開發者來說,在一個復雜的應用程序中,是存在很多分層模型的,但基本思想還是一樣的:每一層都提供了一個干凈的數據模型,從而隱藏了底層的復雜性。通過這樣的抽象來允許不同的人群有效地協同工作。

每個數據模型都包含了如何使用它的假設。有些用法很容易,有些不支持;有些操作很快,有些執行不好;有些數據轉換很自然,有些則很笨拙。由於數據模型對其上層的應用程序能做什么和不能做什么有着深刻的影響,因此選擇適合於應用程序的數據模型十分重要。

(在這一章中,我們將完整的梳理各類數據模型和基於不同數據模型衍生的查詢語言)

2.數據模型

  • 關系型數據模型
    目前對計算機科學具有最深遠影響的數據模型就是SQL,基於Edgar Codd 提出了關系模型的對數據進行組織成表(SQL之中的表),其中每個元組稱之為行,行是一個無序的集合(SQL之中的行)。關系型的數據模型的目標將實現細節隱藏在一個更干凈的接口后面。

  • 非關系型數據模型(NoSQL)
    與關系數據模型相比,非關系型數據模型具有下面的一些優點。包括了:

    • 非常大的數據容量與非常高的讀寫吞吐量。
    • 很好地支持的專門查詢操作
    • 數據模型會更加靈活
舉個栗子:

目前大多數應用程序開發都是使用面向對象編程語言完成的,這導致了對SQL數據模型靈活性的批評:數據存儲在關系表中,應用程序代碼中需要在對象與表、行和列的數據庫模型之間需要一個笨拙的轉換層。(也就是我們日常使用的ORM
LinkedIn是我們常用的職業檔案網站,我們來看看使用不同數據模型的差異。

Linkedin檔案使用關系型數據模型表示

  • 在傳統的SQL模型中,最常見的規范化表示是將位置、教育和聯系人信息放在單獨的表中,帶有外鍵表引用到用戶表,如上圖所示。問題是顯而易見的,多表之間的依賴關系大大的復雜化了應用程序的編寫。

Linkedin檔案使JSON模型表示

  • JSON模型減少了應用程序代碼和存儲層之間匹配問題,它會更加靈活。如上圖所示,JSON表示相比多表模式具有更好的局部性。如果要獲得如教育或職業信息,在 多表模型之中您需要執行多次查詢(通過user_id查詢每個表)或執行一個多表連接的操作。而在JSON的數據模型之中,所有相關信息都在一個位置,一次查詢就足夠完成了。

注:在例子中的前一段,region_id和industry_id給出的ID,不是純文本字符串“Greater Seattle Area”和“Philanthropy”。有如下幾個考量:(1)避免歧義(2)可以統一更新(3)可以更好的本地化來適應不同的語言。使用id的優點是,因為它對人類沒有意義,所以它不需要更改:id可以保持不變,即使它標識的信息是變化的。任何對人類有意義的東西都可能需要在將來某個時候改變,如果信息被復制,所有多余的副本都需要更新。這會導致寫開銷,並且不一致性的風險。區域和行業的列表可能很小,而且變化緩慢,以至於應用程序可以簡單地將它們保存在內存中。**)

文檔型數據模型的靈活性:

當應用程序希望改變其數據格式的情況下,靈活性就顯得至關重要了。 例如,假設我們在數據庫中將每個用戶的全名存儲在一個字段中,而現在想要分別存儲名稱和姓氏。

  • 文檔數據庫中,只需要開始使用新字段編寫新文檔,並在應用程序中有代碼處理舊文檔讀取時的情況。
if (user && user.name && !user.first_name) {
       user.first_name = user.name.split(" ")[0];
}
  • 在關系型數據庫模式中,通常按照這樣的思路修改模型:
ALTER TABLE users ADD COLUMN first_name text;
UPDATE users SET first_name = split_part(name, ' ', 1);	
UPDATE users SET first_name = substring_index(name, ' ', 1);

在一個大數據量的表上運行UPDATE語句可能在任何數據庫上都很慢,因為每一行都需要重寫。如果這是不可接受的,應用程序可以讓first_name設置為其默認為填寫在讀的時候,通過這樣的方式來模擬文檔數據庫的靈活性

小結:文檔型的數據模型的主要優點是模式靈活性,在局部性更好的性能,如程序經常需要訪問整個文檔時具有更好的性能優勢。對於特定的應用程序,它更接近應用程序所使用的數據結構。如果在應用程序中的數據具有類似文檔的結構(即一對多關系樹,通常是一次加載整個樹),那么使用文檔模型會是一個好的選擇。關系型數據模型通過提供更好的連接支持、多對一和多對多關系,如果應用程序使用多對多關系,關系型數據模型會更加適合。通過在數據庫中生成多個請求,可以在應用程序代碼中模擬連接,但這也會將復雜性移動到應用程序中。

文檔型數據庫開始支持表之間的關系查詢,連接操作。關系型數據庫開始引入JSON與XML的支持。混合型的數據模型或許會是數據庫發展的方向

3.數據查詢語言

不知道大家有木有試想過一個問題,為什么我們會有SQL語言。本身使用SQL語句表達的邏輯同樣可以用程序設計語言去表達,為何還需要多此一舉的使用另一種方式去表達數據模型呢?

其實這個答案是非必須的,也就是說,我們可以直接使用程序設計語言來和數據交互。(如:MongoDB就是使用了Js作為原生的交互語言。)但絕大多數我們直接使用的程序設計語言是命令式語言,而像SQL這種代數關系聲明式的查詢語言會有一些更貼合數據模型的優點。

舉個栗子:

例如,如果你有一個動物物種的列表,需要返回列表上的Shark
使用Js的數據表達
使用SQL的數據表達

由上圖所示,命令式語言告訴計算機按一定順序執行某些操作。你可以需要一行一行地單步執行代碼,評估條件,更新變量,並決定是否再循環一次。而在像SQL或關系代數這樣的聲明式查詢語言中,您只需指定您想要的數據的模式,結果必須滿足什么條件,以及您希望如何轉換數據(例如,排序、分組和聚合),而不是具體的實現流程。數據庫系統的查詢優化器來決定哪些索引以及哪些連接方法可以使用,以及執行查詢的各個部分的順序。

  • 聲明式查詢語言通常比命令式語言的API更簡潔,更易於使用。但更重要的是,它還隱藏了數據庫引擎的實現細節,這使得數據庫系統可以在不需要對查詢進行任何更改的情況下引入性能改進。
  • 但SQL在功能上更為有限,靈活性上會受到限制,這給數據庫提供了更多的自動優化空間。
  • 聲明式語言通常適合於並行執行,因為它們只指定結果的模式,而不是用於確定結果的算法。

4.總結

數據模型是一個龐大的主題,所有不同的數據模型。現在都被廣泛使用,它們各自的領域都很好。一個模型可以用另一個模型來模擬,例如,文檔型的數據可以用關系數據庫表示,但結果往往很笨拙。這就是為什么我們有不同的系統為了不同的目的,而不是一個單一的一刀切的解決方案。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM