隨著社交、電商、金融、零售、物聯網等行業的快速發展,現實社會織起了了一張龐大而復雜的關系網,傳統數據庫很難處理關系運算。大數據行業需要處理的數據之間的關系隨數據量呈幾何級數增長,亟需一種支持海量復雜數據關系運算的數據庫,
圖數據庫
應運而生。
1. 圖數據簡介
1.1 何為圖?
學過數據結構這么課程的同學腦海中應該或多或少有 圖
的概念。
形式上,圖是頂點(Vertices)和邊(Edge)的集合,用以表現節點間的接關聯關系;
在圖數據庫的建模中用節點表示實體,用邊表現關系。
在我們的現實生活中,圖表示的關系可以說是無處不在。 Gartner定義了商業世界中5個最重要的圖——社交、意向、消費、興趣和移動,并認為運用這些圖的能力是一個項”可持續的競爭優勢“
1.2 圖數據庫 GraphDB
圖數據庫(Graph database)
并非指存儲圖片的數據庫,而是以 圖
這種數據結構存儲和查詢數據。
圖形數據庫
是一種在線數據庫管理系統,具有處理圖形數據模型的創建,讀取,更新和刪除(CRUD)操作。
與其他數據庫不同,關系
在圖數據庫中占首要地位。這意味著應用程序不必使用外鍵或帶外處理(如MapReduce)來推斷數據的關聯關系。
與關系數據庫或其他NoSQL數據庫相比,圖數據庫的數據模型也更加簡單,更具表現力。圖形數據庫是為與事務(OLTP)系統一起使用而構建的,并且在設計時考慮了事務完整性和操作可用性。
根據存儲和處理模型不同,市面上圖數據庫也有一些區分。
1.2.1 圖存儲
一些圖數據庫使用 原生圖存儲
,這類存儲是經過優化的,并且是專門為了存儲和管理圖而設計的。并不是所有圖數據庫都是使用原生圖存儲,也有一些圖數據庫將圖數據序列化,然后保存到關系型數據庫或者面向對象數據庫,或其他通用數據存儲中。
1.2.2 圖處理引擎
原生圖處理(也稱為 無索引鄰接
)是處理圖數據的最有效方法,因為連接的節點在數據庫中物理地指向彼此。非本機圖處理使用其他方法來處理CRUD操作。
比如:
Neo4J
就是屬于原生圖數據庫,它使用的后端存儲是專門為Neo4J這種圖數據庫定制和優化的,理論上說能更有利于發揮圖數據庫的性能。AllegroGraph
不是原生圖數據庫,而將數據存儲在其他成熟的非圖后端系統上,比如Mysql或者Hbase。
1.3 應用場景
世界上很多著名的公司都在使用圖數據庫。比如:
社交領域:Facebook, Twitter,Linkedin用它來管理社交關系,實現好友推薦
零售領域:eBay,沃爾瑪使用它實現商品實時推薦,給買家更好的購物體驗
金融領域:摩根大通,花旗和瑞銀等銀行在用圖數據庫做風控處理
汽車制造領域:沃爾沃,戴姆勒和豐田等頂級汽車制造商依靠圖數據庫推動創新制造解決方案
電信領域:Verizon, Orange和AT&T 等電信公司依靠圖數據庫來管理網絡,控制訪問并支持客戶360
酒店領域:萬豪和雅高酒店等頂級酒店公司依使用圖數據庫來管理復雜且快速變化的庫存
2. 圖數據 In NoSQL
NoSQL數據庫大致可以分為四類,而圖數據庫正是其一,各種圖數據庫對比,請見下方圖表。
分類 | 數據模型 | 優勢 | 劣勢 | 舉例 |
---|---|---|---|---|
鍵值數據庫 | 哈希表 | 查找速度快 | 數據無結構化,通常只被當作字符串或者二進制數據 | Redis |
列存儲數據庫 | 列式數據存儲 | 查找速度快;支持分布橫向擴展;數據壓縮率高 | 功能相對受限 | HBase |
文檔型數據庫 | 鍵值對擴展 | 數據結構要求不嚴格;表結構可變;不需要預先定義表結構 | 查詢性能不高,缺乏統一的查詢語法 | MongoDB |
圖數據庫 | 節點和關系組成的圖 | 利用圖結構相關算法(最短路徑、節點度關系查找等) | 可能需要對整個圖做計算,不利于圖數據分布存儲 | Neo4j |
3. 圖數據庫 VS 關系型數據庫
與關系型數據庫和 NoSQL 數據庫相比,定義良好的圖數據庫都有著明顯優勢。具體如下
- 性能: 與關系型數據庫和NoSQL存儲處理關聯數據相比,選擇圖數據庫會有絕對的性能提升。隨著數據集的不斷增大,關系型數據庫處理密集join(join-intensive)查詢的性能也會隨之變差,而圖數據庫則不然。在數據集增大時,它的性能趨向于保持不變,這是因為查詢總是只與圖的一部分相關。因此,每個查詢的執行時間只和滿足查詢條件的那部分遍歷的圖的大小(而不是整個圖的大小)成正比。
- 靈活: 圖天生就是可擴展的,這意味著我們可以對一個已經存在的結構增加不同種類的聯系、新節點和新子圖,而不用擔心破壞已有的查詢或應用程序的功能。這些特點對于開發者的生產力和項目風險一般都有積極的意義。同時由于圖模型的靈活性,我們不必在項目最初就窮思竭慮地把領域中的每一個細枝末節都考慮到模型中—這種做法在不斷變化的業務需求面前,簡直就是蠻干。圖的天然可擴展性也意味著我們會做更少的數據遷移,從而降低維護開銷和風險。
- 敏捷性: 因為圖數據庫不需要schema,所以它缺少以schema為導向的數據管理機制,即在關系世界中我們已經熟知的機制。但這并不是一個風險,相反,它促使我們采用了一種更可見的、可操作的管理方式。正如我們在第4章會講到的,圖數據庫的管理通常作用于編程方式,利用測試來驅動數據模型和查詢,以及依靠圖來斷言業務規則。這不再是一個有爭議的做法,事實上這已經比關系型開發應用更廣了。圖數據庫開發方式非常符合當今的敏捷軟件開發和測試驅動軟件開發實踐,這使得以圖數據庫為后端的應用程序可以跟上不斷變化的業務環境。
4. 關系查詢性能對比
在數據關系中心,圖形數據庫在查詢速度方面非常高效,即使對于深度和復雜的查詢也是如此。在《Neo4j in Action》這本書中,作者在關系型數據庫
和圖數據庫(Neo4j)之間進行了實驗。
他們的實驗試圖在一個社交網絡里找到最大深度為5的朋友的朋友。他們的數據集包括100萬人,每人約有50個朋友。實驗結果如下:
深度 | MySQL執行時間(s) | Neo4J執行時間(s) | 返回記錄數 |
---|---|---|---|
2 | 0.016 | 0.01 | ~2500 |
3 | 30.267 | 0.168 | ~110 000 |
4 | 1543.505 | 1.359 | ~600 000 |
5 | 未完成 | 2.132 | ~800 000 |
在深度為2時(即朋友的朋友),兩種數據庫性能相差不是很明顯;深度為3時(即朋友的朋友的朋友),很明顯,關系型數據庫的響應時間30s,已經變得不可接受了;深度到4時,關系數據庫需要近半個小時才能返回結果,使其無法應用于在線系統;深度到5時,關系型數據庫已經無法完成查詢。而對于圖數據庫Neo4J,深度從3到5,其響應時間均在3秒以內。
可以看出,對于圖數據庫來說,數據量越大,越復雜的關聯查詢,約有利于體現其優勢。從深度為4/5的查詢結果我們可以看出,圖數據庫返回了整個社交網絡一半以上的人數。
5. 主流數據圖產品
- Neo4j 業界老大,行業標桿,江湖一哥;
- Nebula 異軍突起,厚積薄發,當紅新銳;
二者搜索熱度對比: https://db-engines.com/en/system/Nebula+Graph%3BNeo4j
具體特性對比:
對比總結
- 性能與成本:Neo4j開源版本是單機的,最少2G內存就可以支持億級別的數據;Nebula性能突出但是維護成本較高,很吃資源(測試環境需要至少8G內存才能啟動);
- 學習成本:Neo4j有專屬查詢語言“Cypher”,Nebula也有自己的“NQL”,二者都需要學習
- 開發成本:Neo4j和Spring緊密合作,對于Java生態支持的更好;Nebula 在這方面剛剛起步
6. Cypher查詢語言
Cypher是Neo4j的圖形查詢語言,允許用戶存儲和檢索圖形數據庫中的數據。
比如下面我們直接通過代碼來對比下 MySQL 和 Neo4j 里面的查詢,我相信即使不寫任何注釋,即使第一次接觸 Neo4j 的人也能輕輕松松的看懂這些查詢語句。
<!-- 1. 全表掃描 -->
<!-- mysql -->
SELECT p.*
FROM products as p;
<!-- neo4j -->
MATCH (p:Product)
RETURN p;
<!-- 2. 查詢價格最貴的10個商品,只返回商品名字和單價 -->
<!-- mysql -->
SELECT p.ProductName, p.UnitPrice
FROM products as p
ORDER BY p.UnitPrice DESC
LIMIT 10;
<!-- neo4j -->
MATCH (p:Product)
RETURN p.productName, p.unitPrice
ORDER BY p.unitPrice DESC
LIMIT 10;
<!-- 3. 按照商品名字篩選 -->
<!-- mysql -->
SELECT p.ProductName, p.UnitPrice
FROM products AS p
WHERE p.ProductName = 'Chocolade';
<!-- neo4j -->
MATCH (p:Product)
WHERE p.productName = "Chocolade"
RETURN p.productName, p.unitPrice;
<!-- 其他的寫法 -->
MATCH (p:Product {productName:"Chocolade"})
RETURN p.productName, p.unitPrice;
<!-- 4. 按照商品名字篩選2 -->
<!-- mysql -->
SELECT p.ProductName, p.UnitPrice
FROM products as p
WHERE p.ProductName IN ('Chocolade','Chai');
<!-- neo4j -->
MATCH (p:Product)
WHERE p.productName IN ['Chocolade','Chai']
RETURN p.productName, p.unitPrice;
<!-- 5. 模糊查詢和數值過濾 -->
<!-- mysql -->
SELECT p.ProductName, p.UnitPrice
FROM products AS p
WHERE p.ProductName LIKE 'C%' AND p.UnitPrice > 100;
<!-- neo4j -->
MATCH (p:Product)
WHERE p.productName STARTS WITH "C" AND p.unitPrice > 100
RETURN p.productName, p.unitPrice;
<!-- 6. 多表聯合查詢-->
<!-- mysql -->
SELECT DISTINCT c.CompanyName
FROM customers AS c
JOIN orders AS o ON (c.CustomerID = o.CustomerID)
JOIN order_details AS od ON (o.OrderID = od.OrderID)
JOIN products AS p ON (od.ProductID = p.ProductID)
WHERE p.ProductName = 'Chocolade';
<!-- neo4j -->
MATCH (p:Product {productName:"Chocolade"})<-[:PRODUCT]-(:Order)<-[:PURCHASED]-(c:Customer)
RETURN distinct c.companyName;
<!-- 7. -->
<!-- mysql -->
SELECT e.EmployeeID, count(*) AS Count
FROM Employee AS e
JOIN Order AS o ON (o.EmployeeID = e.EmployeeID)
GROUP BY e.EmployeeID
ORDER BY Count DESC LIMIT 10;
<!-- neo4j -->
MATCH (:Order)<-[:SOLD]-(e:Employee)
RETURN e.name, count(*) AS cnt
ORDER BY cnt DESC LIMIT 10
下面在看一些更為復雜的例子,我們要查找Joe的所以二度好友:
MATCH
(person:Person)-[:KNOWS]-(friend:Person)-[:KNOWS]-
(foaf:Person)
WHERE
person.name = "Joe"
AND NOT (person)-[:KNOWS]-(foaf)
RETURN
foaf
// Joe認識Sally,Sally認識Anna。Bob被排除在結果之外,因為除了通過Sally成為二級朋友之外,他還是一級朋友。
圖數據庫會經常處理樹形結構數據,必須要遍歷Block樹的最大深度
match (n:Block)
where (n)-[:OWN]->() and not ()-[:OWN]->(n) // 找到根節點
match p = (n)-[:OWN*1..]->(m) //查詢所有從根節點出發的路徑
return p, length(p) as L
order by L desc // 找到路徑長度最大的
limit 1
或者是要從固定節點(aid = 1000)向上尋找到另一個節點(aid=10)的最短路徑
match p = shortestPath( (e:block {aid:10000}) <-[*0..1000]- (r:block {aid:1}) )
return p;
更多cypher語法請閱讀官方文檔: Cypher語法
7. 總結
圖數據庫應對的是當今一個宏觀的商業世界的大趨勢:憑借高度關聯、復雜的動態數據,獲得洞察力和競爭優勢。國內越來越多的公司開始進入圖數據庫領域,研發自己的圖數據庫系統。對于任何達到一定規模或價值的數據,圖數據庫都是呈現和查詢這些關系數據的最好方式。而理解和分析這些圖的能力將成為企業未來最核心的競爭力。
更多學習資料:
- 如何使用Neoj4建模
- Cypher語法
- 深度運算法 https://ramona-chen.top/2020/03/24/neo4j-cha-xun-duo-shen-du-guan-xi-jie-dian/
- Neo4j Java Driver https://neo4j.com/docs/developer-manual/current/drivers/get-started/
- Spring 實體映射關系 https://github.com/neo4j/neo4j-ogm
- 官方學習數據 https://neo4j.com/graphgists/
- 運維 Shell 腳本命令 https://neo4j.com/docs/operations-manual/4.3/tools/cypher-shell/