圖數據庫neo4j和關系數據庫的區別


相信您和我一樣,在使用關系型數據庫時常常會遇到一系列非常復雜的設計問題。例如一部電影中的各個演員常常有主角配角之分,還要有導演,特效等人員的參與。通常情況下這些人員常常都被抽象為Person類型,對應着同一個數據庫表。同時一位導演本身也可以是其它電影或者電視劇的演員,更可能是歌手,甚至是某些影視公司的投資者(沒錯,我這個例子的確是以趙薇為模板的)。而這些影視公司則常常是一系列電影,電視劇的資方。這種彼此關聯的關系常常會非常復雜,而且在兩個實體之間常常同時存在着多個不同的關系:

\

在嘗試使用關系型數據庫對這些關系進行建模時,我們首先需要建立表示各種實體的一系列表:表示人的表,表示電影的表,表示電視劇的表,表示影視公司的表等等。這些表常常需要通過一系列關聯表將它們關聯起來:通過這些關聯表來記錄一個人到底參演過哪些電影,參演過哪些電視劇,唱過哪些歌,同時又是哪些公司的投資方。同時我們還需要創建一系列關聯表來記錄一部電影中哪些人是主角,哪些人是配角,哪個人是導演,哪些人是特效等。可以看到,我們需要大量的關聯表來記錄這一系列復雜的關系。在更多實體引入之后,我們將需要越來越多的關聯表,從而使得基於關系型數據庫的解決方案繁瑣易錯。

這一切的症結主要在於關系型數據庫是以為實體建模這一基礎理念設計的。該設計理念並沒有提供對這些實體間關系的直接支持。在需要描述這些實體之間的關系時,我們常常需要創建一個關聯表以記錄這些數據之間的關聯關系,而且這些關聯表常常不用來記錄除外鍵之外的其它數據。也就是說,這些關聯表也僅僅是通過關系型數據庫所已有的功能來模擬實體之間的關系。這種模擬導致了兩個非常糟糕的結果:數據庫需要通過關聯表間接地維護實體間的關系,導致數據庫的執行效能低下;同時關聯表的數量急劇上升。

這種執行效能到底低下到什么程度呢?就以建立人和電影之間的投資關系為例。一個使用關聯表的設計常常如下所示:

\

如果現在我們想要通過該關系找到一部電影的所有投資人,關系型數據庫常常會執行哪些操作呢?首先,在關聯表中執行一個Table Scan操作(假設沒有得到索引支持),以找到所有film域的值與目標電影id相匹配的記錄。接下來,通過這些記錄中的person域所記錄的Person的主鍵值來從Person表中找到相應的記錄。如果記錄較少,那么這步就會使用Clustered Index Seek操作(假設是使用該運算符)。整個操作的時間復雜度將變為O(nlogn):

\

可以看到,通過關聯表組織的關系在運行時的性能並不是很好。如果我們所需要操作的數據集包含了非常多的關系,而且主要是在對這些關系進行操作,那么可以想象到關系數據庫的性能將變得有多差。

除了性能之外,關聯表數量的管理也是一個非常讓人頭疼的問題。剛剛我們僅僅是舉了一個具有四個實體的例子:人,電影,電視劇,影視公司。現實生活中的例子可不是這么簡單。在一些場景下,我們常常需要對更多的實體進行建模,從而完整地描述某一領域內的關聯關系。這種關聯關系所涵蓋的可能包含影視公司的控股關系,各控股公司之間復雜的持股關系以及各公司之間的借貸款情況及擔保關系等,更可能是人之間的關系,人與各個品牌之間的代言關系,各個品牌與所屬公司之間的關系等。

可以看到,在需要描述大量關系時,傳統的關系型數據庫已經不堪重負。它所能承擔的是較多實體但是實體間關系略顯簡單的情況。而對於這種實體間關系非常復雜,常常需要在關系之中記錄數據,而且大部分對數據的操作都與關系有關的情況,原生支持了關系的圖形數據庫才是正確的選擇。它不僅僅可以為我們帶來運行性能的提升,更可以大大提高系統開發效率,減少維護成本。

 

於是,在搜索更好的方案時無意間發現了圖形數據庫,查閱一番資料后感覺確實是個不錯的選擇,畢竟業界的一些大佬,如twitter,Adobe等也在用。

那么,什么是圖形數據庫呢?在這里我貼上較為官方的定義:a database that uses graph structures for semantic queries with nodes, edges and properties to represent and store data – independent of the way the data is stored internally. It’s really the model and the implemented algorithms that matter.注意,這里只是說數據模型是圖結構的,沒有說數據的存儲也一定要是圖結構的。其數據模型如下圖graphdb-1


進入今天的主題,我將以Neo4j為例,說明為什么選擇圖形數據庫

首先,先簡要介紹一下Neo4j。Neo4j是由Java和Scala寫成的一個NoSql數據庫,專門用於網絡圖的存儲。更詳細的內容可見官網。作為一個圖形數據庫,Neo4j有以下優點:

  • 更快的數據庫操作。當然,有一個前提條件,那就是數據量較大,在MySql中存儲的話需要許多表,並且表之間聯系較多(即有不少的操作需要join表)。
  • 數據更直觀,相應的SQL語句也更好寫(Neo4j使用Cypher語言,與傳統SQL有很大不同)。
  • 更靈活。不管有什么新的數據需要存儲,都是一律的節點和邊,只需要考慮節點屬性和邊屬性。而MySql中即意味着新的表,還要考慮和其他表的關系。
  • 數據庫操作的速度並不會隨着數據庫的增大有明顯的降低。這得益於Neo4j特殊的數據存儲結構和專門優化的圖算法。

接着,試着從更深一些的層次看圖形數據庫。我將從Neo4j的數據存儲和數據讀寫兩方面來說明為什么選它。

  1. 數據存儲
    Neo4j對於圖的存儲自然是經過特別優化的。不像傳統數據庫的一條記錄一條數據的存儲方式,Neo4j的存儲方式是:節點的類別,屬性,邊的類別,屬性等都是分開存儲的,這將大大有助於提高圖形數據庫的性能。如下圖:neo4j-1

  2. 數據讀寫
    在Neo4j中,存儲節點時使用了"index-free adjacency",即每個節點都有指向其鄰居節點的指針,可以讓我們在O(1)

的時間內找到鄰居節點。另外,按照官方的說法,在Neo4j中邊是最重要的,是"first-class entities",所以單獨存儲,這有利於在圖遍歷的時候提高速度,也可以很方便地以任何方向進行遍歷。neo4j-2


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM