NoSQL 能終結關係資料庫嗎?


當然不能,NoSQL不是為取代關係資料庫而設計的

而且是在某些場景下使用NoSQL更加合適,兩者應該算是並列關係

另外附圖一張,基本可以看出關係型資料庫和各種非關係資料庫各自的特點
大概從中可以得到各自適合的場景


NoSQL的大部分非關係模型,在關係型資料庫出現之前,就已經存在了。如果非關係型資料庫真的能非常完美的解決問題,後來也就不需要發明關係型資料庫,然後讓關係型資料庫一統江湖了。

E.F.Codd同時也因為發明了關係資料庫模型而獲得圖靈獎,間接的反應了關係資料庫的重要性。那些很古老的非關係資料庫的重新出現和使用,只是更適合某一些應用場景罷了。


一年前寫過一篇博客,為此對NoSQL資料庫做了一次細緻的研究。總得來說NoSQL是無法終結關係型資料庫的。因為NoSQL自始至終是關係型資料庫的一個真子集。現在市場也冷下來,潮水也褪去,看看剩下來的幾家不是一直在向關係型資料庫演變的道路上嗎?

不然怎麼叫「年年歲歲花相似,歲歲年年人不同」。理論一直沒有變,工具也沒有變得不中用,變的只是使用工具的人而已。


現把自己的博客轉貼在此

------------------------------------------------------------------------------------------------

DarkHouse

  • 博客列表
  • 關於

NoSQL資料庫模型
5

黑屋在「關係型資料庫統治」中提到在關係型資料庫之前,層級資料庫和網狀資料庫適應了當時硬體的性能,成為了大型資料庫系統的主流。 有趣的是老一代資料庫要求應用程序負責數據的獲取邏輯,這和當前流行的NoSQL資料庫如出一轍。當時的開發者必須非常了解數據存儲底層的原理, 由他們決定程序該調用哪些索引,如何以最優的方式獲取數據。可是這樣又產生另一個大問題:一旦數據物理模型發生調整,往往會演變成一次災難。 業務邏輯和數據訪問邏輯被緊緊的耦合在一起,你根本無法預測你在存儲設備上的一次輕微調整(例如擴充一個硬碟)會對上層程序帶來多大的影響。 關係型資料庫正是解決了應用程序和數據訪問方式的耦合問題,才確立了自己的統治地位。


1

然而關係型資料庫解決這個問題主要是在單機環境中。隨著互聯網的興起,單台資料庫伺服器已經無法滿足大數據量、大吞吐量以及跨地理區域等業務要求。 那些標準化的關係型數據產品無法在可控的成本範圍內提供適合的方案,於是一些互聯網公司開始研究適合自己的數據存儲解決方案。 它們對關係型資料庫進行重新解構和裁剪,並吸取以往的一些非關係型資料庫經驗,形成了專門應對互聯網分散式架構下的數據存儲方案。 這類資料庫有著共同的特徵:不支持SQL,但具有靈活的擴展性,因此被統一歸類為NoSQL資料庫。 介紹NoSQL的文章不計其數,然而大多是圍繞其性能、擴展性以及可用性等方面。本文將從數據模型角度描述當前流行的幾種NoSQL資料庫類型, 並將它們同關係模型一一對比。


在這之前,黑屋先要介紹一些重要的概念,這些概念能幫助我們更深入的了解資料庫的內在機制。黑屋認為不管外在的形式如何多樣化, 但凡能抓住本質性的東西,一切將變得格外清晰。資料庫的發展一直是伴隨著計算機硬體的發展,然而很多邏輯上的理念到現在為止也沒有發生太大變化。 關係型模型還是有著不可動搖的地位,很多當前流行的分散式數據模型也是重複著資料庫早期的一些理念,只是在更大的互聯網背景下實踐。 因此在我們進步的同時,時不時的回顧歷史,弄明白為何發展成現在這樣子,思考和歸納一些本質性的東西,更有助於看清以後的方向。


計算機如何存儲數據
3

黑屋一直試圖從數據模型的角度來闡述資料庫的一些本質,並盡量避免介紹工程細節,例如:如何保證數據一致性,如何實現並發性,資料庫日誌是如何記錄和回滾, 如何建立索引,分散式資料庫實現等等。這些工程細節確實是資料庫非常重要的部分,然而並不涉及其本質。本質的東西往往是簡單,正是由於太多的細節把其淹沒, 使得我們忽略了它。對於初學者來說,實在太容易迷失在這些工程實現細節中了。黑屋認為數據模型是資料庫最重要的本質,所有其他東西都是圍繞著它來設計和運行的。 而數據模型又依賴於計算機硬體系統,因此在開始解釋其他東西之前,我們得先弄明白一個最基礎的問題:計算機是如何存儲數據的?或者說數據的物理模型長什麼樣?


如果你在思考「計算機是如何存儲數據」這個問題的時候?第一個想到的是操作系統中的文件夾和文件,那麼你和我想的是一致的。 文件系統才是我們讀取、新建、刪除數據最常用的工具。實際上,文件系統和資料庫系統本質上是一樣的,你可以把文件系統理解為一個特殊的資料庫系統, 或者把資料庫系統理解為一個特殊的文件系統。到底誰包含誰僅僅看你站在哪個陣營里:操作系統or資料庫系統,但這並不妨礙我們對這個問題的理解。 由於現在很多資料庫系統都是直接建立在文件系統之上,那麼我們還是以文件系統來說明這個問題。


1

拋開複雜的文件路徑以及許可權控制,一個文件系統最基本的能力是識別哪些數據是屬於一個文件的。最直觀的想法就是把屬於一個文件的數據存放在硬碟上一塊連續的區域, 然後記錄這個文件在硬碟的起始位置和結束位置就可以了。第二個文件就從第一個文件結束位置的後一位開始,依次類推。現在問題來了,如果我修改了第一個文件, 使得它變大了,那麼從第二個文件開始,所有的後續文件都要向後移,這意味著整塊硬碟的數據都要重寫。但我們知道系統肯定不會這麼做, 因為經驗告訴我們,保存一個文件速度很快。這是因為文件系統一開始就給我們做了一定的規劃,主要是劃分了好多相同大小的連續區域, 規定每個單元區域稱為「塊」(block),其大小為4KB,每個塊在物理設備上的具體位置信息被記錄在引導區,這些位置信息如果是機械硬碟則包括盤號,磁軌和扇區。 我們將這個規划過程叫做文件系統的「格式化」。

現在新建一個文件就以「塊」為最小單位保存,這也就是說哪怕建立一個空文件,它也要佔去4KB的存儲空間。而如果一個文件大小超過4KB, 文件系統會關聯多個4KB的塊來容納這個文件,並盡量做到這些「塊」在物理位置上是連續的。這裡只能說「盡量」,因為一旦文件大小發生變動, 文件系統只能在其他地方找到合適的「塊」來容納多出的部分,而那些被判斷為沒有發生變動的「塊」就不必再被重寫了。一旦發生這樣的情形, 你會發現讀取一個文件的速度變慢了,因為這個文件的內容被散布在硬碟的各個角落,硬碟必須驅動磁臂和磁頭找到這些位置讀取它們, 這便是隨機訪問(Random Access);與之對應的叫順序訪問(Sequential Access),後者的讀取速度通常是前者的100倍。 現在也許你已經明白「硬碟碎片整理」的意思了,沒錯,就是將屬於一個文件的多個「塊」放在連續的位置,這樣就能減少隨機訪問的次數。

有興趣的讀者可以閱讀此文了解更多關於設計一個文件系統的細節。

偏移量和指向

這裡我想總結一下文件系統組織數據的核心思想:偏移量(Offset)和指向(Pointer)。如果數據是連續存放的,通過偏移量的方式可以很容易定位信息。 你可以以不同的層面去理解「連續」,最小的層面是字位(Bit),規定每8個連續的字位為一個位元組(Byte),每4個連續的位元組可表示一個整數; 高一點的層面是文件系統的塊或者就是一個文件——以元數據來描述這個文件的結構模式,並通過偏移量來解析這個文件中所包含的信息。 如果數據無法連續的保存在一起,那麼你可以通過「指向」來關聯相關的數據。當然你也可以從多個層面去理解指向,最容易理解的是宏觀層面上打開一個文件的快捷方式, 或者HTML文檔中的超鏈接,它們都是以「指向」的方式來關聯信息的。在微觀層面上,指嚮往往是一些物理地址,例如硬碟地址,內存地址,或者網路地址等。 在我們接下來的內容中,你會處處體會到計算機系統中這種分形幾何現象,即同一種邏輯或構造在各個層面上反覆出現。因此當你在文件系統層面理解「偏移量」和「指向」, 你就能輕鬆應對更高層面上資料庫系統和應用系統的架構邏輯。下面我將就這兩種數據關聯方式分別作簡單介紹。


圖1.自然界中的分形幾何
1
偏移量

如果相關數據連續保存在一起,那麼我們可以用偏移量來定位具體信息。例如存儲一天的任務清單,每個任務都以具體的時間點作為開始, 後面是具體要做的任務,每個任務的描述不能超過50個位元組;下一個任務緊接著前一個任務,這樣我們就能得到如圖2中的數據結構。


圖2.使用偏移量來定位信息

現在我們要讀取第一個任務的信息,它處於這個文件的開始位置,那麼開始位置的值為1, 一直到第5位是任務的時間信息;從第6位開始到第55位則是任務1的具體內容。 每個任務信息的長度固定都是55(不滿則以空補充)。因此我們很容易確定任務2的開始位置是56,進而可以推斷第n個任務的起始位置為(n-1)*55+1,這就是解讀這個文件的模式(Schema)。 所以偏移量可以理解為一個包含數據起始位置和長度信息的二元組:(起始位置,長度)。只要將相關數據緊挨在一起,並約定每個數據段的長度, 我們便可以通過偏移量來定位具體的信息。


1

也許你會問,為什麼不用分隔符來區分不同數據段信息呢?這樣我們還可以節省一些因長度不滿所造成的空間浪費。 例如針對上面的例子,我們選擇特殊的分隔符,用「|」分割同一行的不同欄位,用「#"分割不同的行, 這樣任務清單的存儲模型變成了圖3的樣子。這當然是沒有問題的,實際上你還可以使用更通用的數據格式協議來定義數據模式,例如XML或JSON等。 但分隔符本質上還是通過確定數據段的起始位置和結束位置來定位信息,因此大可把它們同偏移量歸為同一類數據關聯方式。 值得說明的,偏移量相比於分隔符具有更高的計算機執行效率,你因此需要在時間和空間上權衡到底選用哪種方式。


圖3.使用分隔符來定位信息
指向

如果數據無法保存在一個連續的區域內,那麼我們需要通過指向來關聯這些信息。還是任務清單的例子,假如有一天我的任務實在太多了,以至於一個4KB的塊容納不下, 那麼我只能將多出來的任務存放在另一個4KB大小的塊內。但我必須將這兩個塊通過某種方式關聯起來,以表示這一天所有的任務都在這裡了。 每個塊都有一個編號作為其唯一性標識,並且系統能通過這個編號直接控制硬碟讀取該塊。我們現在可以通過如圖4中的方式將塊1和塊2關聯起來。


圖4.使用指向關聯數據

與圖2不同的是,現在塊的第一行多了一些額外的描述性信息,稱之為元數據。「Date」表示當天的年、月、日,「Prev」表示前續的塊號,「Next」表示後續的塊號。 塊1中Next對應的值是2,意味著還有相關信息保存在塊2中,這樣系統就知道還需讀取塊2中的數據以構成2015年6月19日那天的任務清單。 相反,塊2中對應的Prev是塊1,而Next為空,則表示塊2是最後一個需要讀取的塊了。「Items」表示塊中對應的條目數,塊1中一共容納了71條任務, 因此只剩下50位元組的剩餘空間,即「Free」對應的值。由於50位元組已經無法容納下一個任務了,因此我們只能將後面的任務保存到塊2中。 這些元數據為系統有效組織數據提供了重要的依據,也許有些特性我們暫時沒有想全面,因此預留了一部分「Unuse」的空間為將來之用。


塊1中保存了塊2的邏輯地址,系統再將邏輯地址映射到物理地址,最後讀取了塊2中的內容。這裡實際上同時運用了偏移量和指向兩種方式來關聯數據。 對於那些存放在一個塊中的任務來說,由於它們在物理層面上是連續的,因此它們本來就關聯在一起;而對於那些無法在物理層面上連續存放的任務來說, 只能通過指向從邏輯層面上關聯起來。

圖2~圖4中所描述的並不是我們直觀上那種適合人類閱讀的數據展現形式,而是底層數據存儲的形式。 為了說明方便,圖中用了明文的編碼,更為準確的應該是類似01000101001001010101010101010....這樣的二進位碼。 計算機系統是通過偏移量來識別二進位編碼,規定每8個字位為1個位元組,一個字母佔用1個位元組,一個整數佔4個位元組。

規範化和聚合

偏移量和指向經常結合在一起使用的,在文件系統中,通過這兩種方式來關聯屬於一個文件的數據。正如前面提到計算機系統是基於分形幾何學的, 對應到資料庫模型,有兩種與之對應的更高層面的叫法:聚合(Aggregation)和規範化(Normalization)。 前者很容易顧名思義,將相關聯的數據聚合在一起,通過偏移量來定位各個欄位;而對後者的理解,需要回顧一下Codd在其論文中對Normalization的描述。 簡單的說,規範化是降低數據冗餘的過程,一張規範化的二維表是指每行每列只能對應一個具有基本數據類型的值;而當遇到多值等複雜數據類型的時候, 需將其規範成多張簡單二維表,並通過外碼建立它們之間的關聯。


圖5.規範化和聚合

圖5描繪了分別用規劃化和聚合兩種方式對電商領域產品的實體建模。最初,我們可以說,所有的產品都有一個ID,價格,和描述。 接下來,我們發現不同類型的產品有不同的屬性,如書本有作者而牛仔褲有尺寸。其次,實體中有的屬性是一對一,而有的一對多,例如一個音樂專輯很多曲目。 我們很容易發現規範化就是「指向」高一級的表現形式,而聚合則對應的是「偏移量」。

規範化要求我們儘可能打散信息,以便能降低數據的冗餘度,提高數據操控的精確度;而聚合則希望我們能從整體上把握數據,因為粗粒度能提高數據的操作效率, 但卻會產生大量的數據冗餘。資料庫建模本質上需要考慮的就是如何在這兩種方式間權衡,這很難用隻言片語描述清楚。我們可以用物理學來作一個類比: 研究物理你既可以微觀到量子理論,亦可宏觀到天體宇宙學,兩種方式都有各自的研究難度,最後你又隱隱約約覺得它們可能是相通的。 同樣最嚴格的規範化是要把信息打碎到原子級別。何謂原子級別?對應到資料庫模型層面可理解為一個實體所具有的一個屬性,如果再對這個屬性分解就沒有信息價值了。 我們用銷售訂單來舉例說明一下。


一個銷售訂單至少包含商品、客戶、數量、金額、日期等屬性,當然一定還有一個唯一性的訂單號。原子級別的規範化要求我們對這些獨立屬性建立對應的表來存儲。 這意味著我們得用5張表來存儲這些信息,分別是:SalesOrderProduct,SalesOrderCustomer,SalesOrderQuantity,SalesOrderAmount,SalesOrderDate。 這5張表都是以訂單號為主碼。


圖6.規範化後的銷售訂單相關表

如圖6所示,徹底規範化的數據模型具有以下三個優勢:

  • 每個屬性信息只需保存一次,因此沒有必要考慮複雜耗時的數據同步問題。
  • 每次改動只會影響需要變動的部分,如果將這些屬性聚合成一行來保存,修改其中一個屬性勢必會影響其他屬性的訪問。
  • 你可以靈活的調整數據模型,如果你需要為銷售訂單再增加一個屬性,例如「銷售稅」,那麼只需再新建一個表來保存這些信息即可, 原來的銷售訂單數據不會受任何影響。

與之對比,我們將圖7中的數據模型採用反規範化(Denormalizing)的方式處理,得到一張聚合了各個屬性的銷售訂單表(SalesOrder)。 也許圖7中銷售訂單模型才更符合我們的習慣,因為這幾個屬性是銷售訂單的基本要素,它們之間一一對應,而且經常一起出現。 將它們聚合在一起給我們帶來的便利性遠遠大於完全規範化後的收益。數據一旦被分散保存在多張窄表中,會導致重構一個實體需要發生多次JOIN, 而不同的表很有可能分散在硬碟不同的角落,加大了隨機訪問的概率,會造成很大的性能損失。


圖7.反規範化後的銷售訂單表

資料庫規範化在關係型資料庫建模中是一項非常重要的技術,一般要求數據模型要達到3範式。但這不是一條金科玉律,設計者往往需結合實際, 權衡各方面的性能需求,適當的聚合數據提高冗餘度。
1

聚合和規範化如同一個硬幣的兩面,規範化反向操作會提高了聚合度,而聚合的反向操作則會提高規範度。 對NoSQL資料庫來說,往往是先考慮將數據聚合在一起,再根據需要逐步規範化。而正是從聚合到規範化的轉變過程中,演變出許多不同類型的NoSQL資料庫。 圖8很形象的表現了這個演變過程,以及各個點上大家所熟知的NoSQL資料庫。有趣的是它們都是向著SQL的方向進化,又重新演繹了上個世紀發生的類似過程。


圖8.NoSQL資料庫模型的演變
1
NoSQL的到來

互聯網應用的高並發訪問量、大數據存儲量以及跨地理區域等性質使得傳統的基於關係型資料庫的應用架構無法滿足其要求。 在傳統的企業應用架構中,資料庫往往處於系統集成的結合點上,如果兩個應用之間具有高度的相關性,那麼就應該將這兩個應用合在一起,共享同一個資料庫實例。 這樣數據的一致性、原子性以及可用性就能由關係型資料庫得到充分保證。而資料庫被要求只能安裝在單機環境中,這樣才能保證數據在一個存儲空間中。 即使是那些高端的高可用性解決方案,也被要求至少要使用共享的磁碟組。那麼單機的資料庫伺服器到底受哪些條件限制,使得它再也無法提高? 我們從以下三個維度看:

  • 並發訪問量:一台普通關係型資料庫伺服器一般只能接受每秒100個並發訪問連接, 並且不管你如何擴大內存或者增加CPU,提高的空間都非常有限。這是因為關係型資料庫具有很強的數據一致性和原子性校驗, 如果兩個會話連接(Connection Session)同時訪問同一條記錄,先到的那個會話會在這條記錄上加一個排他鎖,這導致後一個會話只能等待前一個會話完成後才能有所動作。 而如果前一個會話是要修改這條記錄,那麼很有可能會涉及磁碟讀寫操作,這會讓第二個會話會等得更久。這僅僅是2個會話,而如果同一秒中有100個會話, 這意味著發生相互等待的概率非常大。等待的會話不能及時釋放系統資源,而後續的訪問請求又源源不斷進來,最後導致系統突然間無法提供服務,即所謂的「雪崩」效應。
  • 最大存儲量:理論上,關係型資料庫是沒有最大存儲量限制的。但隨著數據量的增大,資料庫的性能確實會隨之下降。 直接影響性能的是那些超級大表,這些表在一個資料庫中往往不會超過10個,卻可能佔據了整體80%以上的空間。在實際使用過程, 你會發現一旦表的條目數達到上億的級別,那麼對該表的查詢會遇到嚴重的性能問題,這個時候擴充伺服器的性能也是無濟於事的。 大多數資料庫針對這些大表的解決方案是做橫向的分區(Partition),這確實能緩解一些性能問題,但數據量增大對運維工作帶來的成本提升卻是難以克服的。 無論是新建索引、資料庫重組還是資料庫備份都要花上好幾個小時甚至天以上的時間單位。當資料庫大到一定程度,就無法有效備份了。
  • 跨地理區域:在標準的三層架構中,資料庫伺服器和應用伺服器是分開部署的,但考慮網路傳輸等因素,往往被安置在同一個機房。 現在想像一下一個互聯網應用它的資料庫伺服器在紐約,而為了滿足中國市場,又在上海部署了一套應用伺服器。這樣能否提高中國用戶訪問的速度? 答案是不能,因為應用伺服器與資料庫伺服器之間的通訊還需跨越太平洋底下的光纜,這反應在數據通訊上是高延遲性(受狹義相對論約束:任何信息傳輸無法超過光速)。 只有在上海同時部署一個資料庫伺服器的副本,才能解決跨地理區域的性能問題。但這樣上海和紐約兩個副本之間數據的同步與一致性就無法再得到關係型資料庫的庇護了。

以上三個問題預示著只有採用分散式架構才能應對互聯網級別應用的特性。然而一旦這麼做,意味著同樣的數據可能會出現多個副本, 對任何一個副本所做的更新都需要同步的其他副本上。想像一下,當你提交一個訂單,需要等待部署在不同地理位置上相距很遠的多個資料庫都保存成功了, 才彈出提示框,告訴你訂單已經成功提交。由於網路的延遲,反應到前端等待時間是無法忍受的;而且一旦其中一個副本沒有更新成功,就會造成副本間的數據不一致。 為了達成一種妥協,只能忍受數據暫時的不一致,並希望通過後續非同步的數據交換,實現所有副本數據的最終一致。

關於分散式資料庫有一個著名的CAP理論, 描述在數據一致性(Consistency)、可用性(Availability)和分區容錯性(Partition tolerance)這三者之間,你只能很好的滿足其中任意兩個,而無法做到三個同時滿足。

許多互聯網公司覺得標準的關係型資料庫產品無法滿足它們對擴展性、可用性以及性能上的要求,於是轉而開發符合自身應用特點的數據存儲方案。 這類數據存儲方案有著共同的特點就是支持分散式但不支持SQL,通過調用更為底層的API來對數據進行操作。於是更多的企業和組織跟進,都根據自身應用的特點去定製化資料庫。 這類資料庫沒有出現一些標準化的產品,但它們統一被歸為非關係型資料庫,或者更習慣上稱之為「NoSQL資料庫」。

很多文獻將「NoSQL」理解為「Not Only SQL」,黑屋認為這和實際不符。很多BI產品在SQL的基礎上擴展了一些OLAP元素,但它們明顯不屬於NoSQL的範疇。 SQL是一種命令式腳本語言,用戶通過SQL可以實現任何符合邏輯的數據集合操作,而無須告知系統該如何去實現。關係型資料庫在設計上被要求盡量滿足SQL的標準, 即盡量從使用者角度考慮,把複雜的計算邏輯封裝成容易調用的人機介面。從模型角度理解「關係型」和「非關係型」是有邏輯偏差的,因為所有資料庫原則上或多或少滿足關係模型。 然而從通用性和易用性角度理解則相對容易,關係型資料庫具有良好的通用性和易用性;而非關係型資料庫或者NoSQL資料庫是滿足特定領域的定製化資料庫。

說到這裡其實有個很大的疑問:難道去除了對「SQL」的支持,就能滿足擴展性、可用性以及高性能了嗎?如果真是這樣,那就把現有的關係型資料庫的SQL功能禁用掉,不也可以嗎? 對於前一個問題的答案是否定的,而對於後一個問題的答案黑屋認為是可行的。事實上,NoSQL資料庫就是關係型資料庫的一個工程子集,你只要關閉或者禁用關係型資料庫的某些功能, 就能將之塑造成一個NoSQL資料庫。但令人遺憾的是,你拋棄的那部分功能是要在應用層面上還回來的。也就是說你要在應用層面重寫原來由資料庫完成的一些功能特性。 對於習慣於依賴成熟關係型資料庫產品解決方案的公司和組織來說,開發這種底層數據處理特性實在是太難了,因此NoSQL資料庫到目前為止還是那種技術性公司和組織的專屬玩具。 所以,確切的說不是關係型資料庫無法支持分散式,而是傳統的基於關係型資料庫的應用架構和運維能力無法支持分散式。


在以下的內容中我將對目前流行的幾種NoSQL資料庫作簡單的介紹,它們分別是:鍵值資料庫(Key-Value Stores),列族資料庫(Column-Family Databases), 文檔資料庫(Document Databases),和圖形資料庫(Graph Databases)。我會從資料庫模型層面來闡明它們之間的不同主要體現在聚合和規範化的程度。 如果將聚合和規範化的轉變過程看成一個連續體,左邊是最聚合的狀態,右邊是最規範化的狀態,那麼無疑鍵值資料庫是屬於最左邊的,而處於最右邊的可不是關係型資料庫(這裡允許我先賣個關子)。 在分析每種NoSQL資料庫模型的時候,我都將嘗試使用關係型資料庫來塑造類似的效果,這能讓我們更清楚的看到不同資料庫間的相通性。

圖9.聚合和規範化連續體
鍵值資料庫

鍵值資料庫是所有資料庫中最精簡的形式,也可以說所有資料庫本質上都是鍵值資料庫。 前面講的文件系統也是一個鍵值資料庫,它的Key是文件名(包含路徑),Value則對應文檔的內容。 然而NoSQL中的鍵值資料庫在實現上通常是一張大的哈希表,每個Value被指定一個唯一性的Key,通過一個哈希函數計算, 可將Key直接對應到Value的存儲位置信息上,然後便能快速訪問Value對應的數據。這裡Key就是Value的一個「指向」,而Value對資料庫來說是模糊的, 它可以是以二進位形式(BLOB)保存的任何數據結構。應用程序通過一個Key獲取對應的Value後需要自己負責解析這個二進位串,基於這個原因, 鍵值資料庫只能支持最簡單的針對單個Key的查詢(get)、插入(put)和刪除(delete)操作。


鍵值資料庫是最有可能也是最容易實現分散式部署的,因為每個Key對應的Value都是相互獨立的,不存在任何指向關聯,而所有的數據關聯都已經聚合在一個Value里了。 為了保證數據能均勻的分布在不同的分區伺服器(Partition)上,鍵值資料庫需要選擇合適的哈希函數來決定數據存放的位置。 首先確定數據保存在哪個分區伺服器,接著是分區伺服器上的具體存儲位置。這裡我們又看到計算機系統呈現的分形幾何:在單機環境下,數據從不同的硬碟上匯聚到內存作聚合, 而在分散式環境下,硬碟被放大成了一台獨立的伺服器,數據從不同的分區伺服器上匯聚到應用伺服器中作聚合(見圖10)。


圖10.鍵值資料庫的分區實現

現在我們試著用關係型資料庫來實現和鍵值資料庫類似的存儲模型。我們需要做的是創建一張包含2列的表:第一列為Key, 類型為128位的字元型; 第二列為Value, 類型為BLOG,無長度限制;然後註明在第一列上建立一個哈希索引,這就差不多了。但為了防止一些校驗功能帶來的性能損耗, 我們還可以關閉日誌功能、事務原子性支持、並發鎖功能(如果確定不大可能出現同時操作同一條記錄的情況)。我們還是可以通過SQL來訪問這個表的數據, 因為SQL只會在第一次訪問的時候編譯,以後便會留有一個編譯後的緩存;而對這張表的操作也就3個SQL語句,所以這不會損耗太多性能。 這樣我們就得到了一個用關係型資料庫實現的鍵值資料庫,雖然有點委屈,但性能上也不會輸給一個純粹的鍵值資料庫太多,而且一旦有調整的需要, 我們還可以馬上恢復一些禁用掉的功能。

關於哪些是影響SQL資料庫性能的主要因素,可參考StoneBraker的這篇文章"SQL vs NoSQL"。

鍵值資料庫一般用於存儲一些臨時性的東西,而且一定要用在分散式的架構中才能最大發揮其優勢。最常見的應用場景例如CDN服務, 對網頁中大量圖片,Javascript代碼建立就近緩存點,加快用戶打開網頁的速度。在大多數鍵值資料庫的應用中,我們還發現一般都將其完全內存化(In-memory), 因為很多情況下這些數據可以從其他數據源(例如關係型資料庫)還原,數據的持久化因此變得沒有那麼重要了。 還有一些應用場景對Key是有順序性要求的,例如獲取Key在某個範圍內所有的Value, 這時就要用BTree來代替哈希函數了。 一旦添加了這個能力,那麼對分區將帶來不小的挑戰,你只能根據Key的範圍來分區,而這很難做到數據在各分區間的平衡。


列族資料庫

列族資料庫之所以能在眾多NoSQL資料庫中脫穎而出不得不說是因為Google公司BigTable名聲在外。 BigTable主要被用於GoogleAnalytics和GoogleMap等應用,它的主要特點是在能提供高擴展性和大數據存儲的同時,還能保證一定的數據分析能力。 列族資料庫或者說BigTable類資料庫相比於鍵值資料庫要豐富得多,列族(Column-Family)的意思是將具有相關性的列聚合成一個存儲單元。 例如客戶的基本信息包括姓名、稱謂等,客戶的地址信息包括街道、城市、州、郵編等,那麼我們將客戶基本信息和地址信息分別看成兩個不同的列族, 它們包含的每個「name/value pair」就是列族的列,不同的列族通過相同的「Row Key」關聯起來。


圖11.列族資料庫邏輯模型

從圖11中列族資料庫的邏輯模型上看不出什麼特別之處,僅僅是把關係型數據原來橫著排的列並成了豎排。但是這種把相關性強的屬性組成一組, 不同的組相互區分開的形式在物理模型上是具有很大意義的。這就是前面我們描述的聚合和規範化應用的一個實例,列族資料庫本質上是根據實際需要來權衡聚合和規範化的程度, 做到一個合理的安排。這個安排就是將相關性強的信息聚合到一起,相關性弱的信息用不同的列族來規範化。


與關係型資料庫不同的是,列族中的列沒有嚴格的模式定義,它可以被自由定義並任意添加。例如圖11中,客戶1的地址信息與其他客戶在模式上是不同的, 作為一個英國的客戶他只有Country沒有State, 他的郵編的叫法和格式都與美國的客戶不同。事實上很多情況下,列都不一定是靜態的, 例如一個以股票代碼為Row Key的列族資料庫,其中一個列族記錄每天的收盤價,那麼列名就是當天的日期,它是動態的。


儘管圖9中客戶基本信息和地址信息是放在一塊兒的,然而在物理層面上這兩個列族會生成兩個不同的文件,這意味著你可以分別將這兩個文件存放在不同的硬碟上, 這樣的垂直分割能實現對兩個列族並行訪問,並且在操作上相互隔離(圖12),這也更有利於在MapReduce框架下做海量數據分析。


圖12.不同的列族分開存儲

那麼用關係型資料庫是否可以模仿列族資料庫?這取決於你的關係型資料庫是否支持將表建立在不同的文件里,據我所知, Oracle是可以通過定義表空間來實現這樣的配置的。那麼假設在Oracle的環境下,我們為每個列族創建一個包含Row Key和Column Family兩列的表, 表名即為列族的名字。其中Column Family這列的數據類型是沒有長度限制的String,用於保存類似JSON串形式的「列名/列值對」。 我們還可以使用內建的壓縮技術對該列中的數據進行壓縮,如果該列保存了相對長的字元串,就會得到一個不錯的壓縮率。 這個表需要獨享一個表空間,並把不同表空間對應的數據文件保存到不同的硬碟上。這樣我們基本上就完成了對一個列族資料庫的模仿, 你還是可以用SQL來實現所有對列族資料庫的操作,甚至還可以使用JOIN來關聯兩個不同列族的數據。 當然,你還是得自己完成分散式架構的設計,包括實現一些副本的冗餘、負載的均衡、數據同步等問題,你還得藉助第三方的MapReduce框架來支持海量數據的操作。

數據壓縮技術應用到資料庫不僅可以提高空間使用率,也可以顯著提高性能,因為同樣一次讀盤可以獲取更多的數據。 雖然解壓過程耗費一定的CPU時間,但和I/O時間相比可以忽略不計,何況現實情況中CPU都處於飢餓狀態,利用率不高。 甚至有些壓縮技術可以在不需要解壓的情況下完成某些數據操作,這樣效率就更高了。

文檔資料庫

在所有NoSQL資料庫中,文檔資料庫可謂是最火熱的。它最能讓用戶猶豫:到底是選擇用文檔資料庫呢,還是關係型資料庫? 文檔資料庫的吸引力在於靈活的數據結構和方便的橫向擴展能力。在大多數人印象中文檔資料庫就是性能的保證,使用它就能輕鬆解決關係型資料庫無法處理的大數據問題。

本質上講,文檔資料庫只是在鍵值資料庫的基礎上豐富了點內容。首先,Value不再對資料庫完全模糊,而是以一種半結構化的文檔形式呈現。 「文檔」在這裡更傾向於一種將相關數據聚合在一起的一個實體,一般以XML、JSON或者TXT(偏移量)等通用數據格式來組織。 其次,應用程序不僅可以通過Key來獲取數據,也可以通過文檔中的某個屬性值來查詢和過濾數據。 這個特徵使得文檔資料庫能滿足一些基於複雜查詢條件的應用需求,也讓它看起來更像是一個關係型資料庫。


圖13.文檔資料庫邏輯模型:銷售訂單

與關係型資料庫建模的規範化理念不同,文檔資料庫更願意接受一定的數據冗餘以便能將相關信息存放在一個實體文檔中,這樣做可以避免產生過多的小文檔。 如圖13中的銷售訂單的文檔模型,文檔資料庫建議將整個銷售訂單的數據聚合在一個實體中,這樣就能根據訂單號一下子獲取一張完整的銷售訂單信息。 而在關係型資料庫中,一般會將銷售訂單規範化成銷售訂單抬頭表和銷售訂單行項目表,前者存放抬頭的共享信息,後者存放屬於該訂單的多個行項目。 關係型資料庫需要通過SQL的JOIN操作關聯這兩張表中的數據,以便Denormalize成類似圖13中的文檔形式。雖然訪問單個訂單的效率關係型資料庫不如文檔資料庫, 但如果需要統計銷售量最大的產品,那麼關係型資料庫只需遍歷行項目表就可以了,而文檔資料庫則要遍歷更多的數據。


但即使是文檔資料庫,你也不能無限制的使用聚合,你還是得花很多心思去考慮規範化的問題。 如圖13中,客戶和產品只是保存了一個ID,並沒有將客戶和產品的實際屬性聚合到銷售訂單這個實體中。這樣做是有理由的,當你更新一個客戶數據或者產品數據時, 你不必再去遍歷整個銷售訂單庫來同步這些更新了。然而當你想知道某個城市的銷售額,你必須得先從客戶資料庫中獲取屬於該城市的所有客戶, 然後根據這些客戶再去銷售訂單資料庫中過濾滿足條件的銷售訂單,並累計銷售額。需要說明的是,文檔資料庫一般不支持JOIN操作, 上面所說的所有邏輯你必須在應用程序層面自己實現。


我們是否可以用一個關係型資料庫實現文檔資料庫最主要的兩個優點呢?先說數據結構的靈活性,同列族資料庫一樣, 我們為每個文檔庫建立一個包含Row Key和Document兩列的表,其中Document列的類型為String(可以限定長度為4000Byte,也可以不限長度), 用於保存JSON格式的字元串。這樣我們雖然可以得到一個靈活的數據結構,但卻無法使用關係資料庫內建的索引機制。 不過我們還是可以用一種變通的方式實現,如果我們想對某個屬性建立索引,我們只需再建立一個表,該表的主碼為需要被索引的屬性(可多個), 而非主碼欄位可以是一些描述性的或者數字性的欄位。如圖14,我們通過客戶ID的胖索引(Fat Index)可以快速找到一個客戶對應的所有訂單號, 甚至無須訪問主表,就能累計每個客戶的消費。但這就要求應用程序在更新主表的時候還需同時更新相應的索引表, 幸運的是我們還是可以用到關係型資料庫Transaction的機制來保證這兩邊數據的一致性。


圖14.客戶ID的胖索引表實現

那麼擴展性(Scale-Out)呢?確實許多文檔資料庫具有內建的Replication和Sharding功能,也正因為這兩點才使得文檔資料庫能支持海量的數據和高並發訪問量。 從前面的描述中不難發現,其實單台的文檔資料庫的性能並不能凌駕於關係型資料庫之上,甚至在綜合能力方面也毫無優勢可言。那麼現在的問題就轉化為: 關係型資料庫是否也可以內建Replication和Sharding功能?從理論上是完全可行的,文檔資料庫之所以支持這些橫向擴展能力, 完全是因為放棄了一些數據一致性的要求,這和支持的是文檔模型還是關係模型毫無關係。 事實上,MySQL就已經有了類似的橫向擴展解決方案。


文檔資料庫這種介乎鍵值資料庫和關係型數據中間的狀態有時候使得它很難正確找到自己的定位。 如果你還是個新手,那麼從一個相對容易、內容積累還不是很多的文檔資料庫入手是一個不錯的選擇。 它能讓你了解一些資料庫本質性的東西,但你最後還是無法忽略關係型資料庫,即使它到現在已經發展得極其複雜令人髮指。 文檔資料庫以Denormalized的形式保存數據的特點使得它在一個特殊的應用領域具有良好的適用性,這便是數據歸檔。 將保存在關係型資料庫中一些老舊的歷史數據遷移出來保存到文檔資料庫中,既能緩解關係型資料庫的壓力,又能很好的滿足對這些歷史數據的操作和存儲要求。


圖形資料庫

圖形資料庫(Graph Databases)可以說是NoSQL資料庫中的一個異類,如果說其他NoSQL資料庫更喜歡用聚合來關聯數據, 那麼圖形資料庫則是徹底規範化的數據模型,它高度依賴於用指向來關聯數據。也許你早已知道了答案,在我們前面的聚合和規範化連續體中,圖形資料庫與鍵值資料庫就是兩個對應的極端。 處於極端的事物總是在某些方面具有絕對的優勢,鍵值資料庫的優勢在於獲取單個實體數據時是最快的;而圖形資料庫更關注實體與實體間的關係(Relationship), 因此它在各個實體和關係間的遍歷是最有效率的。


圖形資料庫主要存儲三類信息:其一是和所有資料庫一樣的實體信息,稱之為Node,不同之處在於Node中不會保存具體的屬性內容,而是屬性和關係的指向。 其二是描述實體間關係的信息,稱之為Edge。Edge具有方向性,例如: 「Mary是Jack的妻子,Jack是Mary的丈夫」描述的是婚姻這種關係的兩個不同方向。 同Node一樣,Edge也擁有屬性信息,因此除了保存「開始Node」和「結束Node」的指向外,還保存其自有的屬性指向。 最後是屬性信息,Node和Edge都將各自的屬性內容保存在一個地方,並通過指向鏈的方式關聯在一起,這種設定使得Denormalize一個實體信息需要通過多次隨機訪問, 但也意味著你可以靈活添加或刪除Node和Edge的屬性。圖形資料庫最適合用來描述系統性集群組織,例如圖15便是用圖形數據模型描述的公司組織結構。


圖15.圖形數據模型:組織結構

上圖中兩個Node的之間的關係都是雙向的,例如部門與僱員間存在「部門Employs僱員」和「僱員Work In部門」兩個獨立的關係。 這樣設計的好處在於遇到諸如「哪些僱員在Manufacturing部門工作?」時,不需要遍歷所有的僱員節點來檢查是否有該部門的「Work In」關係, 而是直接將「Manufacturing部門」設置為起點,獲取其下所有「Employs」關係,再以這些關係為指向,便能快速獲取所有僱員節點。 在上圖的例子中,我們還可以發現「Work In」關係擁有自己的屬性,即僱員的受雇日期。這在邏輯是必須的,因為「受雇日期」既不能單獨賦予僱員, 也不能單獨賦予部門,它只能用於描述僱員和部門之間發生的僱傭關係。

似乎在「關係」上加上時間信息是具有一定通用性的,黑屋認為在存儲一段「關係」的時候將開始日期和結束日期作為兩個默認屬性是值得考慮的。

對圖形資料庫來說,影響性能的主要因素是一次遍歷所經歷的節點數,而對資料庫容量的大小並不敏感。但它並不能像關係型資料庫那樣能處理錯綜複雜的數據分析, 而僅僅是在處理「關係」上更勝一籌。在關係型資料庫統治中我們也曾提到過關係模型之前的網狀模型,當時的網狀資料庫雖然也是通過節點間的指向來關聯信息, 但是這種關聯和信息間的導航是與前端業務邏輯緊密綁定的。圖形資料庫相比網狀資料庫最大的進步在於它實現了一種通用型的網狀模型, 基於Node、Edge以及關聯的屬性,它原則上可以對現實中的任何事物建模。這種最高級別的規範化就好比構成一個原子的質子、中子和電子, 是構建萬事萬物的基礎。所以圖形資料庫在某種程度被認為是下一代的關係型資料庫。

在前文中,我們還提到過實體-關係模型(ER Model),這也是一種注重實體間「關係」的建模方式。從邏輯層面上說它和圖形模型是完全相通的, 你可以毫無費力的將一個實體-關係模型轉變成圖形模型,反之亦然。但在具體實現的物理模型層面上,實體-關係模型是基於關係型資料庫的, 實體和關係都是以二維表的形式保存,並以Join操作實現「實體-關係-實體」的導航;而圖形資料庫則在鍵值資料庫的基礎上優化了這種指向關聯方式, 使其無論在性能還是數據結構的靈活性上都更勝一籌。


大家都已經習慣應用實體-關係模型在關係型資料庫之上建模,這也充分說明圖形模型的普適性;至少在邏輯層面上大家非常容易接受這種建模方式, 因為現實事物本就是呈網狀關聯的。但我在這裡還是想嘗試在關係型資料庫的基礎上實現一個圖形資料庫,不僅僅在邏輯層面上, 也要在性能和數據結構的靈活性上更接近一個圖形資料庫。那麼首先我們需要創建三個表,分別是:NodeTable, EdgeTable和PropertyTable(見下圖)。


圖16.用關係型資料庫實現圖形數據模型

NodeTable有4個列,第一列Node ID是主碼,用於唯一標識一個Node;它的數據類型是整數,這樣能稍微提高些BTREE索引訪問的效率。 第二列Tag用於區分Node的類別,我們將不同類別的Node統一存放在一個表裡而不是分開建表,這樣就能保證對前端應用的一致性;如果數據量過大, 可考慮根據Tag列來建立分區(Partition)。第三列In Use用於標識該Node是否已被刪除(一般不直接從表裡刪除數據)。 第四列Properties Pointer是屬性的指向,Node的表裡不直接保存屬性的內容。EdgeTable的第一列和第二列分別表示一條邊的起始節點和結束節點, 它們是該表的聯合主碼,默認情況下基於這兩列的主索引是排序的;這樣的設定能保證根據一個Start Node ID快速獲取所有屬於該節點的關係, 因為相同的Start Node ID在物理位置是連續的,可以避免過多的隨機讀取。Edge Name是對Edge的歸類,必要情況下可以根據該列做分區。 與Node一樣,Edge也只保存屬性的指向,但Edge還有另外兩列Valid From和Valid To用於表示一段關係的有效期,如果今天的日期不在有效期內, 那麼就認為該關係已經失效了。所有的屬性都統一保存在PropertiesTable里, 它的主碼是由Properties Pointer和屬性名Name組合而成; 同樣主索引的排序能保證同一個屬性指向下的所有屬性(Name/Value Pairs)能在物理位置上連續。Value的數據類型可以是Binary或者String, 用於存儲各種數據類型。


我們用圖16中的三個表基本上實現了一個圖形資料庫的主要特徵,無論從數據結構的靈活性,還是性能上看,都會相當接近一個純粹的圖形資料庫。 當然,要讓它實際運作,還缺少一些元數據表和應用層面的工程實現細節,但整體思路可以從這三個表來呈現。對於訪問介面來說,我們還是可以用SQL, 但完全可以根據實際需要,封裝一些通用的圖形遍歷操作介面,因此在介面易用性上也不會差太多。如果我們想對某個屬性創建索引, 那麼我們可以像前面文檔資料庫中描述的那些通過創建一個表來實現,它的主碼為要屬性的值,另一列則為Node或Edge的ID。 我們以「&_&」的形式來命名這個索引表,這樣應用程序就知道應該怎麼利用索引去查詢和過濾了。


實際上,這就是一個多租戶架構的數據存儲模型,如果你了解SalesForces的底層架構,你就知道它們是有多麼的相似。 黑屋也一直在嘗試將圖形資料庫模型應用於SaaS領域,創造一種靈活的通用型多租戶數據存儲解決方案, 但這裡還有很長的路要走,難度在於那些看似矛盾的需求間的權衡:靈活性和性能、一致性和分散式、聚合和規範化等。 從目前來看,圖形資料庫已經擁有很多成熟的應用場景,例如:社交網路,導航系統的路徑計算,計算機網路管理,數字營銷的推薦系統, 數據挖掘,複雜系統的許可權和訪問控制等。如果你的應用也落在上面的範圍內,不凡考慮一下圖形資料庫。


總結

我們從計算機如何存儲數據開始,討論了數據是如何在底層進行組織的,並見識了計算機系統中的分形幾何現象。文件系統通過偏移量和指向來關聯數據; 而到了資料庫層面,我們主要平衡聚合和規範化的程度;在應用系統集成層面,我們考量的是緊耦合還是松耦合。 所有這些系統架構思維在底層共享著相同的內核,掌握它有助於我們從錯綜複雜的表像中看清實質,進而靈活應用到其他層面上。


我們後面又討論了NoSQL資料庫的到來,由於傳統的基於關係型資料庫的應用架構無法支撐互聯網規模的應用,於是很多互聯網公司開發了適合自身應用的數據存儲方案。 這類以不提供SQL支持為主要特徵的資料庫成為關係型資料庫之外的第二種選擇,它們以提供高性能和高的擴展性在分散式應用系統架構中得到越來越廣泛的關注。 然而NoSQL資料庫的性能和靈活性並不是平白無故產生的,它們大都是以犧牲一致性來換取的。在這點上我們無法忽略關係型數據已取得的成就。


NoSQL資料庫相比關係型資料庫是簡單的,它們之中甚至還沒有出現成熟的商業化產品。在生產環境中應用它們還需藉助其他一些組件,如:集群管理、負載均衡、消息中間件等; 因此NoSQL在很多情況下被看成是一種工具集,你必須配套使用它們,甚至還需要自己完成一些定製開發。這就好比DIY一台電腦, 你需要了解每個組件的特性以及它們之間如何相互磨合,才能組裝出一台適合你的完美電腦。對年輕的學習者來說,NoSQL無疑充滿了吸引力, 他們不必從封裝得很好卻複雜得毫無頭緒的成熟資料庫產品入手,去追趕前輩們訂立下來的規矩;他們現在可以直接接觸到資料庫的Alpha版本(鍵值資料庫), 並隨著前端業務的發展逐漸體驗資料庫在不同時期的進化。這比看著一款成熟產品的手冊,調整那些莫名其妙的參數實在要有意思多了。


然而我們也不能因此忽視關係型資料庫的地位,認為它一定會被NoSQL資料庫取代。在後面的內容中,我分別介紹了4種常見的NoSQL資料庫類型, 並將它們一一在關係型資料庫上近似實現。我想說明的是當前所有的NoSQL資料庫都只能算關係型資料庫的一個工程子集,它們並沒有什麼先進性。 對比單機環境下一切性能優勢都是假象,這隻能說明你對關係型資料庫產品不夠了解。作為成熟的產品,關係型資料庫需要考慮: 如何面向普通的使用者提供簡便性和易用性?如何能支持所有的軟硬體平台?如何能支持所有的應用場景?因此它固然會損失一些性能。 然而對於一套經過定製化開發,並部署在定製化硬體系統上的NoSQL資料庫系統來說,一個專業化團隊才是保證其性能優越的關鍵。


1

關係型資料庫可以作為一個很好的考量基準,畢竟40多年的發展使得它已經總結出了許多數據處理的經驗。 因此,當你推薦一個項目使用NoSQL資料庫的時候,你一定要對比它與關係型資料庫的差距,你同時也要心裡有數, 這些丟失的功能特性很有可能需要項目團隊在應用層面上去完成,而這又嚴重依賴於團隊的能力以及項目時間和成本上的容忍程度。 對於大部分應用場景來說,只要你認為資料庫伺服器能在單機環境中部署,那麼關係型資料庫永遠是最佳選擇。 隨著數據量和訪問量的逐步上升,在你決定使用分散式架構之前,不凡先考慮使用鍵值資料庫(In-Memory)做一些緩存機制,使用文檔資料庫歸檔一些在線的歷史數據, 或者使用列族資料庫降低在線關係型資料庫的OLAP壓力。這種將NoSQL資料庫作為關係型資料庫一種補充,聯合使用多種數據存儲方案的架構具有更好的可操作性和成本收益。


不能。

(1)應用場景不同,各有優缺點。可以參考下 CAP 理論。
能做到海量數據的產品並不多,所以大部分產品並沒有這個必要去使用 NoSQL。

(2)
既然各有優缺點,為什麼要終結呢?
現在已經有了一些嘗試結合兩者的資料庫,典型的比如 MongoDb。
而傳統資料庫也在嘗試加入 NoSQL 相關特性。


不能


NoSQL也好,NewSQL也好,都是對資料庫的一種擴充,其基本存儲原理,即使是「分散式存儲」也可能70年代就有了,沒有什麼特別革命性的東西,問題的關鍵在於現在處理的數據類型(很多非結構化數據),數據量(TB-PB級)和以前很大不同,和關係型資料庫也有很大不同。NoSQL之盛行和過去10-15年間關係型資料庫的突破不大或者忽視互聯網/非結構化數據有很大關係,或者說是對關係型資料庫過去的「不作為」的一種懲罰和警示。

NoSQL和關係型資料庫更像是從南坡和北坡攀登珠峰,各自有各自擅長的東西,然而又都有各自不擅長的東西,二者之間不存在取代關係,而更多值得我們關注的是二者在峰頂聚合時的情景,那個時候,似乎可以認為我們目前存在的數據問題有了比較好的平台級解決方案。


這個問題就好比Java能終結C嗎?兩者本來就是不同的可選項,有著不同的問題域,不能一概而論,NoSQL只是SQL的補充。The rise of NoSQL databases marks the end of the era of relational database dominance. But NoSQL databases will not become the new dominators. Relational will still be popular, and used in the majority of situations. They, however, will no longer be the automatic choice. Martin Fowler.


我收錄了一篇文章,專門描述NoSQL和RDMS的關係和各自在大數據上發揮的作用:Big Data: NoSQL or Traditional Database 原文作者是Michael Kopp,Compuware技術策略師,翻譯了其發布了一篇從APM(Application Performance Management)方面看NoSQL以及傳統關係型資料庫的文章。講述了當應用程序因為資料庫慢下來時,不要一味的抱怨資料庫。在這裡不妨多看一下應用程序的本身,因為有時候是應用程序的邏輯設計掣肘著資料庫的性能。Michael Kopp擁有十年以上C++、Java/JEE的架構及開發經驗,現Compuware技術策略師,專攻大規模產品部署的架構和性能。


其實是先有的NoSQL(非關係資料庫),才有的RDBMS(關係資料庫)
如果NoSQL能終結關係資料庫的話,關係資料庫還會出現嗎?


sql和面向對象兩個貌似先進,實則無用有害的概念浪費了大量程序員青春。
這兩個概念都把一些簡單的事情複雜化了。
nosql和介面把這兩個概念簡化了。


每一種新的技術出現,都是為了填補一片空白,而不是為了推翻或完全替代其他技術
NoSQL資料庫設計的目標就確定了它在海量數據存儲查詢方面的優勢,但相應的它也要為此捨棄部分能力,譬如數據一致性以及事務管理上。
NoSQL只是為我們在不同業務場景下,提供了更多的選擇,而不是對關係型資料庫取而代之!


為啥一定要終結,和平相處,在自己最適合的領域發力


不能


這不是一個非此即彼的選擇,是一個互通共融的機會。NOSQL和關係型資料庫產生的北京都不一樣,談不上KILLER終結者,但是NOSQL基於KV,擴展性好,確實是迎合了一部分關係型資料庫實現起來非常困難的場景,但是不能一概而論!


先完美的解決事務吧


NOSQL還是採用SQL的那一套理論,最後還是想做到更好的事務一致性。個人見解,與導師隨便聊聊的一句話。


改良後的關係型資料庫基本能終結 NOSQL。所謂基本,就是類似於現狀的SQL、NOSQL市場佔有率。
所有的技術都是為滿足業務而生。
資料庫的本質是為滿足數據的 寫(存儲)、查詢。
大家知道,NOSQL是先於SQL誕生。但由於,SQL通過範式化的寫入、標準化SQL語言的查詢,滿足並簡化了業務,然後一統天下。
現今之所以NOSQL強勢回歸,是由於「當數據關係層級多、數據多(分庫)後,通過join查詢的效率低下,SQL 無法滿足低延遲的讀寫速度(重點是讀)」。
後面,有時間再來說關係資料庫的改良


應用場景不同,不存在終結的問題


nosql給了軟體研發多一些選擇,降低了創業者在資料庫方面的成本,縮短學習周期。在一致性方面還有待提升呀。oracle 公司也有nosql解決方案,基於Hadoop的設計。


怎麼現在動不動就是,誰能不能取代誰,誰能不能搞死誰。這兩東西明顯優劣勢分布錯開。幹嘛要取代。


NOSQL資料庫未來能終結關係資料庫。畢竟NOSQL的數據模型更多樣化,但是缺乏標準操作語法。


推薦閱讀:

mysql開發資料庫命名規範問題?
解釋一下關係資料庫的第一第二第三範式?

TAG:雲計算 | 互聯網 | 移動互聯網 | 資料庫 | NoSQL | 資料庫設計 | 關係資料庫 |