NOSQL這個概念其實唱了好多好多年了,但是真正浸淫其中, 理解深刻并享受到紅利的人占比其實并不高。
近期筆者自己會在大數據、圖數據等方面邊學習邊記錄一些筆記,持續分享自己的心得體會,此文權當發力之前的開山篇,希望更多關心該領域的朋友多多關注、支持和幫助。
NOSQL的概念
剛剛出現NOSQL這個概念的時候,很多人都是似而非的字面理解成"不是SQL", 與傳統的關系型數據庫是兩個完全獨立的陣營,實際上完全不是這么回事。個人更傾向于理解NOSQL的誕生更多的是為了補充關系型數據庫的短板,滿足現下互聯網海量數據、高并發、低延遲和非結構化數據易擴展等需求。
NoSQL = Not Only SQL,意即“不僅僅是SQL”,是對不同于傳統的關系型數據庫的數據庫管理系統的統稱。與關系型數據庫相比,它們在架構和數據模型方面做了“減法”,而在擴展和并發等方面做了“加法”。
NOSQL簡史
NoSQL一詞最早出現于1998年,是Carlo Strozzi開發的一個輕量、開源、不提供SQL功能的關系數據庫。
2009年,Last.fm的Johan Oskarsson發起了一次關于分布式開源數據庫的討論,來自Rackspace的Eric Evans再次提出了NoSQL的概念,這時的NoSQL主要指非關系型、分布式、不提供ACID的數據庫設計模式。
2009年在亞特蘭大舉行的"no:sql(east)"討論會是一個里程碑,其口號是"select fun, profit from real_world where relational=false;"。因此,對NoSQL最普遍的解釋是"非關聯型的",強調Key-Value Stores和文檔數據庫的優點,而不是單純的反對RDBMS。
為何要使用NoSQL
NoSQL具有靈活的數據模型,可以處理非結構化/半結構化的大數據
NoSQL很容易實現可伸縮性(向上擴展與水平擴展)
NoSQL在不太影響性能的情況,就可以方便的實現高可用的架構
NoSQL數據庫都具有非常高的讀寫性能,尤其在大數據量下,同樣表現優秀。這得益于它的無關系性,數據庫的結構簡單。
NOSQL的分類
主流的NoSQL數據庫主要分為4類:
鍵值(Key-Value)存儲數據庫
這一類數據庫主要會使用到一個哈希表,這個表中有一個特定的鍵和一個指針指向特定的數據。Key/value模型對于IT系統來說的優勢在于簡單、易部署。但是如果DBA只對部分值進行查詢或更新的時候,Key/value就顯得效率低下了。例如:Redis,Memcache, DynamoDB等
列存儲(Wide-Column)數據庫
這部分數據庫通常是用來應對分布式存儲的海量數據。鍵仍然存在,但是它們的特點是指向了多個列。這些列是由列家族來安排的。如:Cassandra, HBase。
文檔型(Document)數據庫
文檔型數據庫的靈感是來自于Lotus Notes辦公軟件的,而且它同第一種鍵值存儲相類似。該類型的數據模型是版本化的文檔,半結構化的文檔以特定的格式存儲,比如JSON。文檔型數據庫可 以看作是鍵值數據庫的升級版,允許之間嵌套鍵值。而且文檔型數據庫比鍵值數據庫的查詢效率更高。如:CouchDB, MongoDB。
圖形(Graph)數據庫
圖形結構的數據庫同其他行列以及剛性結構的SQL數據庫不同,它是使用靈活的圖形模型,并且能夠擴展到多個服務器上。NoSQL數據庫沒有標準的查詢語言(SQL),因此進行數據庫查詢需要制定數據模型。許多NoSQL數據庫都有REST式的數據接口或者查詢API。 如:OrientDB, Neo4J, Titan等。
其他還有類似對象數據庫,XML數據庫大家自行搜索吧。另外很多NOSQL數據庫其實是支持多模型的,比如OrientDB同時支持Key-Value, Document, Graph, Object數據庫。
更多NOSQL數據庫列表請看
http://nosql-database.org/
十萬個為什么
列數據庫到底牛逼在哪里
其實應該這么說,列數據庫只有在OLAP,或者說對部分列進行聚合操作的場景下, 比如sum、count、groupby之類的運算,它確實優秀。但是如果是OLTP,大量的更新或者大量的整行查詢,那列數據庫沒有優勢,甚至反而會比RDBMS更慢。
列數據庫的存儲方式與行數據庫也有顯著不同:行式存儲中,主鍵是rowid,由它關聯到索引數據;列式存儲中,主鍵是數據本身,關聯回rowid,即“數據即索引”。
這里有個對比的paper, 有興趣的可以讀一下
http://db.csail.mit.edu/projects/cstore/abadi-sigmod08.pdf
列存儲 vs 行存儲 WIKI
https://en.wikipedia.org/wiki/Column-oriented_DBMS
文檔DB?VS鍵值DB
它倆的主要區別簡單一句話,就是:鍵值DB不知道Value的格式和內容,而文檔DB知道且可以在格式化的Value內容(Json/XML)上建立索引進行查詢。
我是不是說的挺明白的?
圖DB做社交關系為什么快
我們就以社交網絡為例,來簡要說明下圖數據庫到底快在哪里。 如下我們有個朋友關系表:
> SELECT * FROM friends;
+-------------+--------------+
| user_id ? ? | friend_id ? ?|
+-------------+--------------+
| 1 ? ? ? ? ? | 2 ? ? ? ? ? ?|
| 1 ? ? ? ? ? | 3 ? ? ? ? ? ?|
| 1 ? ? ? ? ? | 4 ? ? ? ? ? ?|
| 2 ? ? ? ? ? | 5 ? ? ? ? ? ?|
| 2 ? ? ? ? ? | 6 ? ? ? ? ? ?|
| 2 ? ? ? ? ? | 7 ? ? ? ? ? ?|
| 3 ? ? ? ? ? | 8 ? ? ? ? ? ?|
| 3 ? ? ? ? ? | 9 ? ? ? ? ? ?|
| 3 ? ? ? ? ? | 10 ? ? ? ? ? |
+-------------+--------------+
對于關系型數據庫來說,這種多對多的模型,除了基本的users表之外, 這個朋友之間的映射關系表必然需要建一張。
也就是說雖然我們RDBMS這么多年的數據庫設計,比如ER設計中的Relationship或者以外鍵的形式存在,或者以中間表的形式存在。
我們現在需要查詢這樣一個場景,找userid=1用戶的朋友的朋友,也就是社交網絡里的2度查詢,大家想想這個SQL應該怎么寫(不難,大家自己試驗一下吧)。
問題是在互聯網海量數據的社交模型中,2度查詢太簡單了,6度查詢或者更高呢?你這個SQL語句還能寫出來么或者說能跑出來么?(6度查詢的笛卡爾積是相當恐怖的數字)。
但是對于圖數據庫而言,Relationship關系是一等公民(在圖數據庫領域一般叫做Edge, 圖中的箭頭), 與上圖中用戶本身的頂點Vetex(圖中的圓)是相同的地位。
在圖數據庫中,我要查詢userid=1用戶的朋友的朋友,只需要先定位到Vertex(1),然后從這個頂點遍歷所有的friend Edge, 就可以查詢出想要的結果,就算是6度查詢,也不過是多了幾層遍歷而已,這個性能的消耗是線性的,完全不是關系型數據庫笛卡爾積的指數性增長可比!
100個用戶可能區別不大,但如果是100w的用戶關系圖譜,對于圖數據庫而言都是從一個點來遍歷,性能沒有明顯的區別。
有個比較好理解的類比,想象你作為一個觀眾坐在八萬人體育館看球賽,這是一場沒人關注的比賽,賽場只做了100個人,那在你座位旁邊的人(視作有關系)是有限的幾個人,或者甚至旁邊沒人;但是如果這是一場同城德比超級火爆的比賽,賽場坐滿了八萬人,坐在你旁邊跟你有關系的人其實還是有限的那幾個而已(有限“度”的遍歷),離你遠的人對從你開始的遍歷沒有任何顯著的影響!
這就是圖數據庫的魅力, 我應該說明白了吧?
再來幾個裝逼理論
六度分離問題
六度分離(六度區隔)理論(Six Degrees of Separation):“你和任何一個陌生人之間所間隔的人不會超過五個,也就是說,最多通過五個人你就能夠認識任何一個陌生人。”
根據這個理論,你和世界上的任何一個人之間只隔著五個人,不管對方在哪個國家,屬哪類人種,是哪種膚色。
這個理論也是做社交網絡的一個基本理念。
柯尼斯堡七橋問題
-- 一筆畫問題
在哥尼斯堡的一個公園里,有七座橋將普雷格爾河中兩個島及島與河岸連接起來(如圖)。問是否可能從這四塊陸地中任一塊出發,恰好通過每座橋一次,再回到起點?歐拉于1736年研究并解決了此問題,他把問題歸結為如右圖的“一筆畫”問題,證明上述走法是不可能的。
這個問題的解決被世人作為圖論的起源來看待,歐拉也由此被稱為“圖論之父”。