NoSQL數(shù)據(jù)庫在整個數(shù)據(jù)庫領(lǐng)域的江湖地位已經(jīng)不言而喻。在大數(shù)據(jù)時代,雖然RDBMS很優(yōu)秀,但是面對快速增長的數(shù)據(jù)規(guī)模和日漸復(fù)雜的數(shù)據(jù)模型,RDBMS漸漸力不從心,無法應(yīng)對很多數(shù)據(jù)庫處理任務(wù),這時NoSQL憑借易擴展、大數(shù)據(jù)量和高性能以及靈活的數(shù)據(jù)模型成功的在數(shù)據(jù)庫領(lǐng)域站穩(wěn)了腳跟。
目前大家基本認(rèn)同將NoSQL數(shù)據(jù)庫分為四大類:鍵值存儲數(shù)據(jù)庫,文檔型數(shù)據(jù)庫,列存儲數(shù)據(jù)庫和圖形數(shù)據(jù)庫,其中每一種類型的數(shù)據(jù)庫都能夠解決關(guān)系型數(shù)據(jù)不能解決的問題。在實際應(yīng)用中,NoSQL數(shù)據(jù)庫的分類界限其實沒有那么明顯,往往會是多種類型的組合體,例如OrientDB就是兼具文檔數(shù)據(jù)庫的靈活性和圖形數(shù)據(jù)庫管理鏈接能力的文檔-圖形數(shù)據(jù)庫管理系統(tǒng),它是圖形數(shù)據(jù)庫,但其中每個節(jié)點又都是文檔。
在正式介紹NoSQL數(shù)據(jù)庫之前,我們先來看看關(guān)系型數(shù)據(jù)庫,關(guān)系型數(shù)據(jù)庫正努力向規(guī)范化看齊,確保每個數(shù)據(jù)塊只存儲一次,例如你要存儲一個人的信息和他的興趣愛好,這時你需要建立兩個表來分別存儲基本信息和興趣愛好。從下圖我們可以看出,除了這兩個表之外,還需另外建立一個表把這兩個表關(guān)聯(lián)起來,
信息表和愛好表之間的關(guān)系是多對多,一個人可以有多個興趣愛好,一個興趣愛好也可以有多個人來練習(xí)。
列存儲數(shù)據(jù)庫
傳統(tǒng)的關(guān)系數(shù)據(jù)庫是行存儲的,每行具有一個行id,并且行中的每個字段存儲在表中。 比方說,如果你要查詢一個人的興趣愛好時,這時你需要將信息表和愛好表關(guān)聯(lián)起來,如下圖所示,請注意在這種情況下你有輕微的反規(guī)范化,因為愛好可以重復(fù)。 如果愛好信息只是一個額外的信息,并不是你的用例的必要條件,那么把它作為一列添加到表中也未嘗不可。但如果某個信息的重要性不足以單獨建立一個表,那么它還應(yīng)該建表存儲嗎?
在基于行存儲的數(shù)據(jù)庫中查詢時,無論你需要哪一列都需要將每一行掃描完。假設(shè)你想要在下圖中的生日列表中查詢9月份生日,數(shù)據(jù)庫將會從上到下和從左到右掃描表,最終返回生日為9月的列表。
如果給某些特定列建索引,那么可以顯著提高查找速度,但是索引會帶來額外的開銷,數(shù)據(jù)庫仍在掃描所有列。
而基于列存儲的數(shù)據(jù)庫可以分別存儲每個列,從而可以在列數(shù)較少的情況下更快速地進行掃描;
上圖的布局看起來和行存儲的數(shù)據(jù)庫很相似,每一列都有一個索引。數(shù)據(jù)庫索引是一種數(shù)據(jù)結(jié)構(gòu),允許以存儲空間和額外寫入(索引更新)為代價快速查找數(shù)據(jù)。 索引將行號映射到數(shù)據(jù),列數(shù)據(jù)庫將數(shù)據(jù)映射到行號,采用這種方式計數(shù)變得更快,很容易就可以查詢到某個項目的愛好人數(shù),并且每個表都只有一種數(shù)據(jù)類型,所以單獨存儲列也利于優(yōu)化壓縮。
那么什么時候適合使用行存儲數(shù)據(jù)庫,什么時候有適合使用列存儲數(shù)據(jù)庫呢?列存儲數(shù)據(jù)庫能夠在其他列不受影響的情況下,輕松添加一列。 在面向列的數(shù)據(jù)庫中,很容易添加另一列,但是如果要添加一條記錄時那么就需要訪問所有表。所以行存儲數(shù)據(jù)庫要比列存儲數(shù)據(jù)庫適合聯(lián)機事務(wù)處理過程(OLTP),因為OLTP要頻繁的進行記錄的添加或修改。
列存儲數(shù)據(jù)庫更適合執(zhí)行分析操作,如進行匯總或計數(shù)。實際交易的事務(wù)如銷售類的通常會選擇行存儲數(shù)據(jù)庫,列存儲數(shù)據(jù)庫采用高級查詢執(zhí)行技術(shù)以簡化的方法處理列塊(稱為“批處理”),從而減少CPU使用率,支持MapReduce算法。
鍵值存儲數(shù)據(jù)庫
鍵值存儲數(shù)據(jù)庫是NoSQL數(shù)據(jù)庫中最簡單的,顧名思義,它是一個鍵值對的集合,能夠存儲大量數(shù)據(jù),它的這種簡單性也讓它成為NoSQL中最具擴展性的數(shù)據(jù)庫類型。
▲鍵值存儲將所有內(nèi)容存儲為鍵和值。
鍵值存儲中的值可以是任何值,字符串、數(shù)字,甚至還可以是封裝在對象中的新的鍵值對,下圖是較為復(fù)雜的鍵值結(jié)構(gòu):
▲鍵值嵌套結(jié)構(gòu)。
文檔型數(shù)據(jù)庫
文檔存儲是鍵值存儲的復(fù)雜性的一個步驟:文檔存儲庫可以使用模式來指定某個文檔結(jié)構(gòu)。文檔存儲是NoSQL數(shù)據(jù)庫類型中出現(xiàn)的最自然的類型,因為它們是按照日常文檔的存儲來設(shè)計的,并且允許對這些數(shù)據(jù)進行復(fù)雜的查詢和計算。從關(guān)系數(shù)據(jù)庫存儲方式的角度來看,每一個事物都應(yīng)該存儲一次,并且通過外鍵連接。而文件存儲不關(guān)心規(guī)范化,只要數(shù)據(jù)存儲在一個有意義的結(jié)構(gòu)中就可以,所以文件存儲數(shù)據(jù)庫有自己的適用范圍。
如果我們要將報紙或雜志中的文章存儲到關(guān)系型數(shù)據(jù)庫中,首先我們要對存儲的信息進行分類,文章放在一個表中,作者和相關(guān)信息放在一個表中,文章評論放在一個表中,讀者信息放在一個表中,然后將這四個表連接起來進行查詢。但是文檔存儲可以將文章存儲為單個實體,這樣就降低了用戶對文章數(shù)據(jù)的認(rèn)知負擔(dān)。
圖形數(shù)據(jù)庫
圖形數(shù)據(jù)庫是NoSQL數(shù)據(jù)庫類型中最復(fù)雜的一個,旨在以高效的方式存儲實體來之間的關(guān)系。圖形數(shù)據(jù)庫適用于高度互連的數(shù)據(jù),尤其是社交網(wǎng)絡(luò),科學(xué)論文引用或是資本資產(chǎn)集群。
圖形或網(wǎng)絡(luò)數(shù)據(jù)有兩個主要組成部分:
節(jié)點:實體本身,如果是在社交網(wǎng)絡(luò)中,那么代表的就是人。
邊:兩個實體之間的關(guān)系,這種關(guān)系用線來表示,并具有自己的屬性。另外邊還可以有方向,如果箭頭指向誰,誰就是老板。
如果給定的實體類型和關(guān)系很多,那么圖就有可能變得非常復(fù)雜。下圖的實體數(shù)量已經(jīng)很少了,但是我們看到它已經(jīng)比較復(fù)雜了。圖形數(shù)據(jù)庫如Neo4j支持ACID,而文檔存儲和鍵值存儲支持BASE。
DB-Engines 最近發(fā)布了 2016年12月份的數(shù)據(jù)庫排名,我們可以看到排名前十的數(shù)據(jù)庫關(guān)系型數(shù)據(jù)庫占據(jù)了7位,Oracle雖然一直占據(jù)首位,但是我們可以看到,與去年同期相比,它的得分下降了93.15,而非關(guān)系型數(shù)據(jù)庫的得分與去年同期相比都有不同程度的提高,所以我們有理由相信NoSQL數(shù)據(jù)庫的未來是大有可為的。