現今雲計算的從業人員對NoSQL一詞並不感到陌生,雖然很多技術人員都長期從事關系數據庫的工作,但現在他們對NoSQL技術充滿期待。對於企業來說,從關系型數據庫到NoSQL數據庫轉變絕對是個需要深思熟慮的大改變。這涉及的不僅是軟件的變化,更多的是對於數據存儲上觀念性的變化。
CouchDB專家兼作者Bradley Holt認為NoSQL並不是反SQL的運動,為對應的工作選擇最恰當的工具才是正確的模式。
大多數非關系數據庫都具有快速和可伸縮的特性。通過放棄關系存儲模型和架構,關系數據庫便可脫離由緊密結合的架構所帶來對其施加的限制。應用程序也無需再鏈接數據庫內表中的數據。
MongoDB和CouchDB以及RavenDB(RavenDB是基於Mocrosoft .NET Framework編寫的)等文檔數據庫除了某些特定的轉換外,通常都是通過HTTP為其提供數據,然後將數據存儲為JSON(JavaScript Object Notation)格式的文檔,並提供多種語言的API接口。這三款開源的文檔數據庫都將簡潔、速度和可伸縮性作為其設計的重要指標。RavenDB的創建者Ayende Rahien就表示“RavenDB的設計初衷就旨在快速寫入並讀取”。
NoSQL——關系數據庫的有力補充
現今,NoSQL和文檔數據庫成為關系數據庫的有力補充(而非替代品),同時提供了更多的選擇。如果企業准備將數據遷移,那麼選擇NoSQL的重要標准就是要看CAP(Consistency、Availability和Partition Tolerance),也就是我們所說的一致性、可用性和分區容忍性。但CAP原則要求在分布式系統只能選擇一致性、可用性和分區容忍性其中的兩項。所以如果企業認為一致性是重要的那麼關系數據庫理應是優先選擇的對象。
例如在銀行等應用領域,一致性是非常重要的,這要求必須隨時考慮每個數據塊。而CAP原則中的可用性也不容忽視,某些領域的數據可用性要比等待所有交易數據收集齊全更為重要。最後在水平縮放時,分區容忍性對於文檔數據庫顯得尤為關鍵。但MongoDB並不支持復雜的事務,只支持少量的原子操作,所以不適用於“轉帳”等對事務和一致性要求很高的場合。這就要求需要一個關系數據庫來對交易進行過高級別的控制。
文檔數據庫的關鍵特性
RESTful HTTP API
RESTful API設計就是為了消除創建松散耦合服務時的依賴關系,這也正是過去分布式體系結構的缺陷。雖然要映射到一些協議需要依賴於元數據的可用性以及方法等,但REST API的設計目標就是不依賴於任何通信協議。
眾多NoSQL數據庫都可通過RESTful的方式訪問。這樣可以通過URI的方式建立數據庫連接,而查詢和命令則通過HTTP實現。MongoDB和CouchDB都提供了特定語言的API接口,以便編寫和執行查詢、更新。但MongoDB的默認設置仍然是使用TCP與數據庫進行連接。而RavenDB則具備基於.NET的客戶端API,可簡化與數據庫的交互過程。
單個記錄中的相關數據
大多數人都錯誤的認為非關系數據庫是一種包含沒有相對關系結構的記錄的文件。而文檔數據庫中存儲的數據包含形狀數據——具有節點的樹。數據庫中的每個記錄都是以文檔形式存在的。並具備自我描述的功能,而不依賴於任何其他文檔。
示例代碼1:文檔數據庫(MongoDB)中的典型事例
{
"name" : "Jim",
"scores" : [ 75, 99, 87.2 ]
}
示例代碼2 CouchDB示例
{
"Subject": "I like Plankton"
"Author": "Rusty"
"PostedDate": "5/23/2006"
"Tags": ["plankton", "baseball", "decisions"]
"Body": "I decided today that I don't like baseball. I like plankton."
}
示例代碼3 包含字符串數據、數字和數組的簡單結構。還可在對象內嵌入對象,以獲得更復雜的文檔結構。
{
"BlogPostTitle”: “LINQ Queries and RavenDB”,
"Date":"/Date(1266953391687+0200)/",
"Content":”Querying RavenDB is very familiar for .NET developers who are already
using LINQ for other purposes”,
"Comments":[
{
"CommentorName":"Julie",
"Date":"/Date(1266952919510+0200)/",
"Text":"Thanks for using something I already know how to
work with!",
"UserId":"users/203907"
},
]
}
唯一鍵
所有數據庫都需要鍵。如果不提供鍵系統則會自動在內部創建一個鍵。鍵對於數據庫的索引功能至關重要。自身域中要求有已知鍵,在上面的示例代碼中存在對“users/203907”的引用。這正式RavenDB利用鍵值並允許用戶定義文檔間關系的方式。
以JSON格式存儲數據
共同點都是使用JSON存儲器數據。事實上,CouchDB和RavenDB(以及其他許多數據庫)均采用JSON格式存儲數據。MongoDB對JSON使用稱之為“二進制JSON”(BSON)的轉換,以便能夠執行二進制序列化。BSON是數據的內部表現形式,從編程的角度看開發者不會發現有任何區別。
JSON的簡潔性使其很容易將幾乎所有語言的對象結構轉換為JSON。 因此,開發者可在應用程序中定義對象,然後將其直接存儲在數據庫中。這使得開發人員不需要使用對象關系映射程序 (ORM) 不斷在數據庫架構和類/對象架構之間進行轉換。
MongoDB BSON API的數據類型和約定列表添加了一種數據類型及其他一些數據類型,以便充實JSON中的可用內容。而在一個單元中存儲和檢索相關數據可提供顯著的性能和可伸縮性的優勢。數據庫不必四處查找常用的相關的數據,因為數據都存儲在相同的位置。
類型的集合
與數據庫交互時,應用程序如何知道哪一項代表學生,哪一項代表書,以及哪一項代表博客文章? 數據庫使用集合這一概念解決了這一問題。 對於與特定集合(如學生集合)關聯的任何文檔(無論其架構如何)都可在從該集合請求數據時對其進行檢索。使用字段來指示類型也十分常見。這只是使搜索過程更加輕松,但哪些內容應進入集合,哪些不應進入集合,由開發者的應用程序決定。
架構靈活的數據庫
前面介紹的“示例代碼1”包含自己的架構。 每個記錄負責自己的架構,甚至負責單個數據庫或集合中包含的架構。並且一個學生記錄並不需要與另一學生記錄相匹配。開發者只需利用此靈活性來提高效率。例如,為什麼存儲 null 值? 您可以在屬性(如“most_repeated class”)不具有值時執行以下操作:
"name" : "Jim",
"scores" : [ 75, 99, 87.2 ]
"name" : "Julie",
"scores" : [ 50, 40, 65 ],
"most_repeated_class" : "Time Management 101"
文檔數據庫和領域驅動開發
規劃域類(可能成為數據庫中的文檔)時,開發者可查找通常最為獨立的數據(例如具有其明細項的訂單),並將其作為單個數據結構加以關注。在訂購系統中,可能還有客戶和產品。但或許會在不需要訂單的客戶信息的情況下訪問該訂單,並且可能會在不需要訪問使用產品的訂單的情況下使用該產品。這意味著,盡管會發現許多機會來包含獨立數據結構(如具有其明細項的訂單),但這並不表示在某些情形下可以不必或者不通過外鍵聯接數據。
每個數據庫都提供各種可用模式的指南,並為用戶指明使用哪些模式可以獲得最大成功。 例如MongoDB文檔討論稱為“上級數組”的模式,它可加快在聯接文檔時對相關數據的訪問速度。
在關系數據庫中,重復數據是個錯誤。 對數據庫進行標准化可確保不出現此情況。 使用NoSQL數據庫(尤其是分發數據庫)時,對數據進行逆規范化是必要且可接受的。
查詢和更新
每個數據庫都附帶用於查詢和更新的API。盡管它們可能不是核心API的一部分,但多語言API是通過加載項提供的。其他查詢依賴預定義的視圖和稱為Map/Reduce的模式。此過程的映射階段使用這些視圖,並且各個數據庫的映射職責是不同的。映射還使數據庫能夠跨多個處理器分發查詢處理。化簡階段可獲取映射查詢(如果已分發,則為多個查詢)的結果,並將數據聚合到要返回到客戶端的結果中。
盡管CouchDB要求開發者通過預定義的Map/Reduce視圖進行查詢,但MongoDB(也使用視圖和Map/Reduce)另外提供執行臨時查詢的功能。RavenDB允許使用預定義索引進行查詢,但也支持臨時查詢,並將根據開發者的實際運行時查詢自動為其創建索引。但在大多數時候,當不采用SQL數據庫的已知架構和關系本質時,開發者會丟失的一個功能是執行臨時查詢的功能。通過嚴格控制查詢,文檔數據庫能夠實現其快速性能。
數據庫變革
有許多非關系數據庫都不屬於NoSQL范疇。但既然這扇門已經敞開,就會鼓舞更多人去探索其可用的功能,並考慮如何改進它。
原文鏈接:MSDN 編譯:李智