寫在前面
從去年找工作結(jié)束之后陌粹,就一直沒有再寫博文了溺蕉,不知不覺已經(jīng)過去大半年了T_T奏属。鳥哥也從學(xué)校正式步入職場跨跨,開始了新的旅程~~。最近工作中由于要用到圖數(shù)據(jù)庫相關(guān)的東西囱皿,網(wǎng)上這方面的資料較少而且質(zhì)量也不是很好勇婴,因此決定自己寫一套有用的博文。
鳥哥帶你學(xué)圖數(shù)據(jù)庫之Neo4j系列將會對Neo4j進行全面的介紹嘱腥,系列的第一篇文章打算先簡單介紹一下圖數(shù)據(jù)庫概念耕渴,與傳統(tǒng)數(shù)據(jù)庫的區(qū)別還有體系結(jié)構(gòu)等內(nèi)容,讓大家從整體上先了解圖數(shù)據(jù)庫齿兔。(這部分內(nèi)容主要是從《Neo4j實戰(zhàn)》整理出來的)
概念
在計算機科學(xué)中橱脸,圖形常常被用于表示特定的數(shù)據(jù)結(jié)構(gòu),如組織層級結(jié)構(gòu)分苇、社交網(wǎng)絡(luò)以及處理流程等添诉。在軟件的設(shè)計階段,結(jié)構(gòu)医寿、流程甚至算法也經(jīng)常使用圖形來表示栏赴。面向?qū)ο蠼Y(jié)構(gòu)的計算機系統(tǒng)也是以繼承、組成和對象成員作為圖形建模的靖秩。
但是须眷,在涉及到數(shù)據(jù)保存的時候竖瘾,開發(fā)人員往往不使用圖形的方式,而是試圖將數(shù)據(jù)裝進關(guān)系型表格中花颗,并對其結(jié)構(gòu)規(guī)范化和再規(guī)范化捕传,一直到它看上去完全不是它應(yīng)該表示的東西的樣子。如果能用數(shù)據(jù)的自然形式表示數(shù)據(jù)捎稚,使數(shù)據(jù)的映射更加直觀生動乐横,免去那些從數(shù)據(jù)引擎上存取數(shù)據(jù)的大量重復(fù)的數(shù)據(jù)轉(zhuǎn)換過程,那樣豈不是更好嗎今野?
現(xiàn)在有了圖數(shù)據(jù)庫就可以實現(xiàn)上述的過程了葡公,圖形數(shù)據(jù)庫使用圖形模型將數(shù)據(jù)作為圖形存儲,圖形數(shù)據(jù)庫由頂點和邊構(gòu)成条霜,頂點和邊這兩個圖形可以構(gòu)建任何的圖形催什。
關(guān)系型數(shù)據(jù)庫 VS 圖數(shù)據(jù)庫
假如我們想表示用戶和他的朋友之間的關(guān)系,使用傳統(tǒng)關(guān)系型數(shù)據(jù)庫通常會這樣表示
如果你想要查找某用戶的朋友的朋友宰睡,你必須對表t_user_friend中的所有數(shù)據(jù)做一個join操作蒲凶,然后丟棄你不再感興趣的所有行。對于一個小的數(shù)據(jù)集拆内,這將不會是一個大的問題旋圆。但是,如果這個社交網(wǎng)絡(luò)不斷發(fā)展壯大麸恍,你可能開始遇到一些嚴重的性能問題灵巧。
關(guān)系數(shù)據(jù)庫和Neo4j圖形數(shù)據(jù)庫的重要區(qū)別是數(shù)據(jù)查詢。在Neo4j圖形數(shù)據(jù)庫中抹沪,沒有表和列的概念刻肄,也沒有基于SQL的select和join命令。那么Neo4j如何查詢圖形數(shù)據(jù)庫呢融欧?
答案是像所有的圖形數(shù)據(jù)庫一樣敏弃,Neo4j借用圖論的強大數(shù)學(xué)概念,并作為一個強大和高效率的引擎用于查詢數(shù)據(jù)噪馏。這個概念就是圖形遍歷麦到,圖形遍歷是使Neo4j具有強大處理大型圖形數(shù)據(jù)的主要工具之一。
為什么圖數(shù)據(jù)庫的查詢效率能夠這么高欠肾?
我們分析查詢過程就會發(fā)現(xiàn)瓶颠,為了查詢深度5的所有關(guān)系,MySQL將對t_user_friend表執(zhí)行笛卡兒積運算5次董济,那將產(chǎn)生500005個記錄步清,其中只有1000個是有用的要门,其他的都被丟棄虏肾。Neo4j則只訪問數(shù)據(jù)庫中的節(jié)點廓啊,當沒有更多的節(jié)點可訪問時,它將停止遍歷封豪。
Neo4j在NoSQL領(lǐng)域的地位
NoSQL谴轮,泛指非關(guān)系型的數(shù)據(jù)庫。隨著互聯(lián)網(wǎng)web2.0網(wǎng)站的興起吹埠,傳統(tǒng)的關(guān)系數(shù)據(jù)庫在應(yīng)付web2.0網(wǎng)站第步,特別是超大規(guī)模和高并發(fā)的SNS類型的web2.0純動態(tài)網(wǎng)站已經(jīng)顯得力不從心,暴露了很多難以克服的問題缘琅,而非關(guān)系型的數(shù)據(jù)庫則由于其本身的特點得到了非常迅速的發(fā)展粘都。NoSQL數(shù)據(jù)庫的產(chǎn)生就是為了解決大規(guī)模數(shù)據(jù)集合多重數(shù)據(jù)種類帶來的挑戰(zhàn),尤其是大數(shù)據(jù)應(yīng)用難題刷袍。
目前主流的NoSQL主要分為四個大類:
- 主鍵值存儲
主鍵值存儲代表了最簡單翩隧,但卻非常強大的處理大量并發(fā)訪問數(shù)據(jù)的方法。緩存是一種典型的主鍵值技術(shù)呻纹。主鍵值存儲允許使用非常簡單的結(jié)構(gòu)存儲數(shù)據(jù)堆生,這些數(shù)據(jù)常常在內(nèi)存中,甚至在高并發(fā)環(huán)境下的高速訪問雷酪。 - 列族存儲
列族存儲是將類似的值(或列)作為一組一起存儲在同一列族中(例如淑仆,用戶數(shù)據(jù)或有關(guān)書籍的信息)。 - 面向文檔存儲
很多實際問題(如內(nèi)容管理系統(tǒng)哥力、用戶注冊數(shù)據(jù)以及CRM數(shù)據(jù))的需求看上去像一個文件的數(shù)據(jù)結(jié)構(gòu)蔗怠。面向文檔的數(shù)據(jù)庫正好提供了這樣的一個地方,用以存儲簡單的省骂,然而是高效的蟀淮,無架構(gòu)的文檔數(shù)據(jù)。本文檔模型中使用的數(shù)據(jù)結(jié)構(gòu)钞澳,可以使你添加自包含的文件和關(guān)聯(lián)關(guān)系到該文檔的數(shù)據(jù)中怠惶。 -
圖形(Graph)
圖形數(shù)據(jù)庫使用圖形模型將數(shù)據(jù)作為圖形存儲,圖形數(shù)據(jù)庫由頂點和邊構(gòu)成轧粟,頂點和邊這兩個圖形可以構(gòu)建任何的圖形策治。
Neo4j是一個開源的、高性能的NOSQL圖形數(shù)據(jù)庫兰吟。
Neo4j主要組件
下面我們以一個人與電影關(guān)系的例子來講解Neo4j的主要組件
- 節(jié)點(Nodes)
節(jié)點通常用來表示一個實體以及實體包含的屬性通惫。上圖中的實體就包含了以下屬性(property)
- 關(guān)系(Relationships)
節(jié)點之間的關(guān)系是圖數(shù)據(jù)庫的關(guān)鍵特性,因為它們允許查找相關(guān)數(shù)據(jù)混蔼。一個關(guān)系連接兩個節(jié)點履腋,并保證有一個有效的源節(jié)點和目標節(jié)點。
關(guān)系的節(jié)點可以被組織成任意結(jié)構(gòu),使圖看起來像表遵湖,樹悔政,圖,或復(fù)合實體?——?其中任何一種可以被組合成更復(fù)雜的延旧,豐富的互聯(lián)結(jié)構(gòu)谋国。
下面是一個ACTED_IN關(guān)系,以“湯姆·漢克斯”為源節(jié)點連接目標節(jié)點“阿甘”迁沫。
關(guān)系具有方向芦瘾,我們觀察到,Tom Hanks 節(jié)點有一個outgoing的關(guān)系集畅,而Forrest Gump 節(jié)點有一個incoming的關(guān)系近弟。
屬性(Properties)
屬性是名稱(或鍵)為字符串的命名值。支持的屬性值有:
Numeric
String
Boolean
上述任何一個值的列表標簽(Labels)
標簽是一種命名的圖結(jié)構(gòu)挺智,用于將節(jié)點分組為集合藐吮;所有標記為同一標簽的節(jié)點屬于同一集合。許多數(shù)據(jù)庫查詢可以使用這些集合而不是整個圖形逃贝,從而使查詢更容易編寫谣辞,執(zhí)行起來更高效。一個節(jié)點可以標記為任意數(shù)量的標簽沐扳,包括無標簽泥从,使標簽成為圖的可選添加項。
標簽通常被用于定義的約束和建立索引沪摄。例如躯嫉,代表用戶的所有節(jié)點都可以用標簽標記:用戶。這樣的地方杨拐,你可以問Neo4j只有在您的用戶節(jié)點執(zhí)行操作祈餐,如查找具有給定名稱的所有用戶。
在我們的示例中哄陶,我們將添加個人(:Person)和電影(:Movie)標簽到我們的圖表中帆阳。
為了舉例說明節(jié)點如何可能有多個標簽,讓我們向湯姆·漢克斯節(jié)點添加一個演員(:Actor)標簽屋吨。
- 遍歷(Traversal)
遍歷表示如何查詢一個圖形蜒谤,從起始節(jié)點導(dǎo)航到相關(guān)節(jié)點尚粘,找到諸如“我的朋友喜歡哪些我還沒擁有的音樂”這樣的問題的答案嫉称,或者“如果這個電源關(guān)閉,哪些Web服務(wù)會受到影響首昔?”
如果我們想在這個小示例數(shù)據(jù)庫找到湯姆·漢克斯主演的電影敢课,遍歷將從湯姆·漢克斯節(jié)點開始跟隨任何:ACTED_IN關(guān)系連接的節(jié)點阶祭,然后在阿甘這個節(jié)點結(jié)束(見虛線):
- 路徑(Paths)
在前面的示例中绷杜,可以將返回結(jié)果作為路徑返回:
上面的路徑有一個長度。最短路徑長度為零?-?就是它只包含一個節(jié)點沒有關(guān)系濒募,如下圖所示接剩。
路徑長度為1的例子如下:
索引(Indexes)
一旦你指定了索引,Neo4j會確保你的索引保持更新你的圖形的演變萨咳。通過新索引屬性查找節(jié)點的任何操作都將看到顯著的性能提升。
Neo4j不會自動更新索引疫稿,這意味著培他,當您第一次創(chuàng)建索引時,操作立即返回遗座。但是修改它時舀凛,結(jié)果不會實時返回。只有當索引被設(shè)置為自動索引是途蒋,才會實時地返回結(jié)果猛遍。
如果索引出現(xiàn)問題,結(jié)果可能會處于失敗狀態(tài)号坡。當它失敗了懊烤,它不會被用來加快查詢速度。你可以刪除并重新創(chuàng)建索引宽堆,或者查看日志腌紧,查找失敗的原因。約束(Constraints)
Neo4j可以幫助保持你的數(shù)據(jù)清洗畜隶。它使用約束壁肋。約束允許您指定數(shù)據(jù)應(yīng)該是什么樣子的規(guī)則。任何違反這些規(guī)則的改變將被拒絕籽慢。
小結(jié)
這篇博文主要介紹了圖數(shù)據(jù)庫概念浸遗、與傳統(tǒng)數(shù)據(jù)庫的區(qū)別以及Neo4j主要的組件這些內(nèi)容,讓大家從整體上了解了圖數(shù)據(jù)庫箱亿,至于是否要使用圖數(shù)據(jù)庫還是要根據(jù)項目的具體需求來決定的跛锌。下一篇博文主要介紹Neo4j的查詢語言Cypher。