Neo4j【從無到有從有到無】【N2】存儲連接數據的選項

目錄

1.關係數據庫缺少關係

2.NOSQL數據庫也缺乏關係

3.圖形數據庫擁抱關係

4.摘要


我們生活在一個互聯的世界中。 爲了蓬勃發展,我們需要了解並影響我們周圍的聯繫網絡。

當今的技術如何應對互聯數據的挑戰? 在本章中,我們研究關係數據庫和聚合NOSQL存儲如何管理圖和連接的數據,並將它們的性能與圖數據庫的性能進行比較。 對於有興趣探索NOSQL主題的讀者,附錄A描述了NOSQL數據庫的四種主要類型。

1.關係數據庫缺少關係

數十年來,開發人員一直試圖在關係數據庫中容納連接的半結構化數據集。 但是,儘管關係數據庫最初被設計爲將紙質表格和表格結構進行編纂,但是在嘗試對現實世界中出現的特殊,特殊關係進行建模時,它們確實非常費勁。 具有諷刺意味的是,關係數據庫對關係的處理不善。

關係確實存在於關係數據庫的本地語言中,但僅在建模時才作爲連接表的一種方式。 在上一章對連接數據的討論中,我們提到我們經常需要消除連接實體關係的語義的歧義,並確定其權重或強度。關聯關係無濟於事。 更糟糕的是,隨着異常數據的增加,數據集的整體結構變得更加複雜和不統一,關係模型變得負擔重,需要大的聯接表,稀疏的行以及大量的空檢查邏輯。 連接性的提高在關係世界中轉化爲連接的增加,這阻礙了性能,並使我們難以響應不斷變化的業務需求而發展現有數據庫。

圖2-1顯示了用於在以客戶爲中心的交易應用程序中存儲客戶訂單的關係架構。

該應用程序對該模式的設計產生了巨大的影響,使某些查詢非常容易,而另一些則更加困難:

  • 連接表增加了意外的複雜性; 他們將業務數據與外鍵元數據混合在一起。
  • 外鍵約束只是爲了使數據庫正常工作而增加了額外的開發和維護開銷。
  • 儘管存在模式,但具有可空列的稀疏表仍需要對代碼進行特殊檢查。
  • 僅需幾個昂貴的聯接即可發現客戶購買了什麼。
    • 相互查詢的成本更高。 與“哪些客戶購買了該產品?”相比,“客戶購買了哪些產品?”相對便宜,後者是推薦系統的基礎。 我們可以引入一個索引,但是即使有了索引,也會出現遞歸問題,例如“哪些客戶購買了該產品,還購買了該產品?”隨着遞歸程度的提高,其價格很快變得高得驚人。

關係數據庫在高度連接的域中掙扎。要了解在關係數據庫進行連接查詢的費用,我們來看看一些簡單的和在社交網絡領域不那麼簡單查詢。

圖2-2顯示了用於記錄友誼的簡單聯接表安排。

如例2-1所示,詢問“鮑勃的朋友是誰?”很容易。

示例2-1 鮑勃的朋友

SELECT p1.Person
FROM Person p1 JOIN PersonFriend
ON PersonFriend.FriendID = p1.ID
JOIN Person p2
ON PersonFriend.PersonID = p2.ID
WHERE p2.Person = 'Bob'

根據我們的樣本數據,答案是Alice和Zach。 這不是特別昂貴或困難的查詢,因爲它使用過濾器WHERE Person.person ='Bob'限制了所考慮的行數

友誼並不總是一種自反的關係,因此在示例2-2中,我們提出了對等查詢,即“誰與Bob成爲朋友?”

示例2-2 誰是鮑勃的朋友?

SELECT p1.Person
FROM Person p1 JOIN PersonFriend
ON PersonFriend.PersonID = p1.ID
JOIN Person p2
ON PersonFriend.FriendID = p2.ID
WHERE p2.Person = 'Bob'

該查詢的答案是Alice; 遺憾的是,扎克不認爲鮑勃是朋友。 這種相互查詢仍然易於實現,但在數據庫方面則更爲昂貴,因爲數據庫現在必須考慮PersonFriend表中的所有行。

我們可以添加一個索引,但這仍然涉及一個昂貴的間接層。 當我們問“誰是我的朋友的朋友?”時,問題變得更加棘手,SQL的層次結構使用了遞歸聯接,這使查詢在語法和計算上變得更加複雜,如示例2-3所示。 (某些關係數據庫爲此提供了語法糖(例如,Oracle具有CONNECT BY函數),該函數簡化了查詢,但沒有簡化基礎的計算複雜性。)

例2-3愛麗絲的朋友

SELECT p1.Person AS PERSON, p2.Person AS FRIEND_OF_FRIEND
FROM PersonFriend pf1 JOIN Person p1
ON pf1.PersonID = p1.ID
JOIN PersonFriend pf2
ON pf2.PersonID = pf1.FriendID
JOIN Person p2
ON pf2.FriendID = p2.ID
WHERE p1.Person = 'Alice' AND pf2.FriendID <> p1.ID

即使僅與Alice的朋友的朋友打交道,該查詢在計算上也很複雜,並且不會深入到Alice的社交網絡。 我們進入網絡越深入,事情就變得越複雜,越昂貴。 儘管有可能在合理的時間內回答“誰是我的朋友的朋友?”的問題,但由於友誼程度高,擴展到四,五或六度的查詢會大大惡化。 遞歸聯接表的計算和空間複雜度。

每當我們嘗試在關係數據庫中對連接進行建模和查詢時,我們都會採取行動。除了上面概述的查詢和計算複雜性之外,我們還必須處理架構的雙刃劍。 schema經常被證明既太僵硬又太脆。 爲了破壞其剛性,我們創建了具有許多可空列的稀疏填充表,並編寫了代碼來處理特殊情況-所有這些都是因爲沒有真正的“一刀切”的架構來適應我們遇到的數據的多樣性。 這增加了耦合並且幾乎破壞了任何內聚的表象。 它的脆弱性表現爲隨着應用程序的發展從一種模式遷移到另一種模式所需的額外工作和精力。

2.NOSQL數據庫也缺乏關係

大多數NOSQL數據庫(無論是鍵值,面向文檔還是面向列)都存儲斷開連接的文檔/值/列的集合。 這使得很難將它們用於連接的數據和圖形。

向此類商店添加關係的一種衆所周知的策略是將集合的標識符嵌入到另一個集合的字段中,從而有效地引入外鍵。 但這需要在應用程序級別加入聚合,這很快變得非常昂貴。

當我們查看一個聚合商店模型(例如圖2-3中的模型)時,我們想象我們可以看到關係。 在記錄起始用戶:Alice中看到對order:1234的引用,我們推斷出用戶:Alice和order:1234之間的連接。 這給了我們錯誤的希望,那就是我們可以使用鍵和值來管理圖形。

在圖2-3中,我們推斷出某些屬性值實際上是對數據庫中其他位置的外部聚合的引用。 但是將這些推論轉變爲可導航的結構並不是免費的,因爲聚合之間的關係並不是數據模型中的一等公民—大多數聚合存儲僅以嵌套地圖的形式提供具有結構的聚合內部。 取而代之的是,使用數據庫的應用程序必須從這些平坦的,斷開連接的數據結構中建立關係。 我們還必須確保應用程序與其餘數據一起更新或刪除這些外部集合引用。 如果這種情況沒有發生,那麼商店將積累懸掛的引用,這會損害數據質量和查詢性能。

Links and Walking

Riak鍵值存儲允許使用鏈接元數據來擴充其每個存儲的值。 每個鏈接都是單向的,從一個存儲的值指向另一個。 Riak允許行走任意數量的這些鏈接(使用Riak術語),從而使模型有所關聯。 但是,此鏈接漫遊由map-reduce提供支持,這是相對潛在的。 與圖形數據庫不同,此鏈接僅適用於簡單的圖形結構編程,而不適用於常規圖形算法。

該方案還有另一個弱點。 因爲沒有“向後”指向的標識符(當然,外部聚合“鏈接”不是自反的),所以我們失去了在數據庫上運行其他有趣查詢的能力。 例如,使用圖2-3中所示的結構,詢問數據庫誰購買了特定產品(可能是爲了基於客戶的個人資料提出建議)是一項昂貴的操作。 如果我們想回答此類問題,我們可能最終會導出數據集並通過某些外部計算基礎架構(例如Hadoop)對其進行處理,以蠻力計算結果。 或者,我們可以追溯地插入向後指向的外部聚合引用,然後查詢。爲了結果。 無論哪種方式,結果都是潛在的。

誘人的是,就連接數據而言,聚合存儲在功能上等同於圖形數據庫。 但這種情況並非如此。 聚合存儲不維護連接數據的一致性,也不支持所謂的無索引鄰接,即元素包含指向其鄰居的直接鏈接。 結果是,對於連接的數據問題,聚合存儲必須使用固有的潛在方法來創建和查詢數據模型外部的關係。

讓我們看看其中的一些侷限性是如何表現出來的。 圖2-4顯示了一個小型社交網絡,該社交網絡是使用聚合商店中的文檔實現的。

通過這種結構,很容易找到用戶的直接朋友-當然,假設該應用程序已盡力確保存儲在friends屬性中的標識符與數據庫中的其他記錄ID一致。 在這種情況下,我們只需按直系朋友的ID查找直屬朋友,這需要進行大量索引查找(每個朋友一個),但無需對整個數據集進行強力掃描。 這樣做,例如,我們發現鮑勃認爲愛麗絲和扎克是朋友。

但是友誼並不總是對稱的。 如果我們想問“誰是鮑勃的朋友?”而不是“誰是鮑勃的朋友?”怎麼辦?這是一個較難回答的問題,在這種情況下,我們唯一的選擇是對整個對象進行暴力掃描 尋找包含Bob的朋友條目的數據集。

O標記和蠻力處理

我們使用O表示法來描述算法的性能如何隨數據集的大小而變化。 O(1)算法表現出恆定的時間性能; 也就是說,無論數據集的大小如何,算法都需要花費相同的時間來執行。 O(n)算法表現出線性性能; 當數據集加倍時,執行算法所需的時間加倍。 O(log n)算法表現出對數性能; 當數據集增加一倍時,執行算法所需的時間將增加固定量。 當數據集處於初期階段時,相對性能的提高可能看起來代價很高,但是隨着數據集變得更大,它會迅速消失。 O(m log n)算法是本書中考慮的最昂貴的算法。 使用O(m log n)算法,當數據集增加一倍時,執行時間將增加一倍,並增加與數據集中元素數量成正比的一些額外量。

由於必須考慮數據存儲中的所有n個聚合,因此就複雜性而言,蠻力計算整個數據集爲O(n)。 對於大多數人來說,這太昂貴了。

大小合理的數據集,我們更喜歡使用O(log n)算法(這種算法效率很高,因爲它在每次迭代時都會丟棄一半的潛在工作量),甚至更好。

相反,圖形數據庫爲同一查詢提供恆定順序的查詢。 在這種情況下,我們只需要在圖中找到代表Bob的節點,然後遵循所有傳入的朋友關係即可; 這些關係導致結點代表代表認爲Bob是他們的朋友的人。 這比暴力破解結果便宜得多,因爲它認爲網絡的成員要少得多。 也就是說,它僅考慮連接到Bob的那些。 當然,如果非常與Bob成爲朋友,我們仍然會考慮整個數據集。

爲了避免必須處理整個數據集,我們可以通過添加反向鏈接來對存儲模型進行規範化。 向每個用戶添加第二個屬性(也許稱爲frien ded_by),我們可以列出與該用戶關聯的傳入友誼關係。 但這不是免費的。 對於初學者,我們必須支付增加的寫延遲的初始和持續成本,以及用於存儲其他元數據的增加的磁盤利用率。 最重要的是,遍歷鏈接仍然很昂貴,因爲每個躍點都需要索引查找。 這是因爲聚集不具有局部性的概念,這與圖形數據庫不同,圖形數據庫自然通過真實(而不是固定的)關係提供無索引的鄰接。 通過在非本地商店的頂部實現圖結構,我們可以獲得部分連接的一些好處,但是成本很高。

遍歷比一跳更深的步伐時,這種巨大的成本將被放大。 朋友很容易,但是想像一下要實時計算“朋友的朋友”或“朋友的朋友的朋友”。 使用這種數據庫是不切實際的,因爲遍歷假關係並不便宜。 這不僅限制了您擴展社交網絡的機會,還減少了可獲利的建議,丟失了數據中心中的故障設備,並使欺詐性的購買活動通過網絡流失。 許多系統試圖保持圖形化處理的外觀,但是不可避免地要分批完成,並且不能提供用戶所需的實時交互。

3.圖形數據庫擁抱關係

前面的示例處理了隱式連接的數據。 作爲用戶,我們可以推斷實體之間的語義依賴關係,但是數據模型以及數據庫本身對這些連接不瞭解。 爲了進行補償,我們的應用程序必須從平坦的,斷開連接的數據中創建一個網絡,然後處理出現在非規範化存儲中的所有慢速查詢和潛在寫入。

我們真正想要的是整體的凝聚力圖景,包括元素之間的聯繫。 與我們剛剛看過的商店相反,在圖表世界中,關聯數據存儲爲關聯數據。 域中存在連接的地方,數據中也存在連接。 例如,考慮圖2-5中所示的社交網絡。

在這種社交網絡中,就像在現實世界中連接數據的許多情況下一樣,實體之間的連接在整個域中並沒有表現出統一性,域是可變結構的。 社交網絡是緊密連接,可變結構的網絡的流行示例,該網絡拒絕被一種適合所有人的模式捕獲,也可以方便地拆分爲多個斷開的聚合。 我們簡單的朋友網絡規模不斷擴大(現在,潛在的朋友可以達到6度),富有表現力。 圖模型的靈活性使我們能夠添加新節點和新關係,而不會損害現有網絡或遷移數據,原始數據及其意圖保持不變。

該圖提供了更豐富的網絡圖。 我們可以看到誰愛誰(以及這種愛是否得到回報)。 我們可以看到誰是COLLEAGUE_OF誰,誰是BOSS_OF。 我們可以看到誰在市場之外,因爲他們是MARRIED_TO其他人; 我們甚至可以在DISLIKES關係所代表的社交網絡中看到反社會元素。 有了這個圖形,我們現在可以查看圖形數據庫在處理連接數據時的性能優勢。

圖中的標籤

通常,我們希望根據網絡中的節點所扮演的角色對其進行分類。 例如,某些節點可能代表用戶,而另一些節點代表訂單或產品。 在Neo4j中,我們使用標籤來表示節點在圖中扮演的角色。 由於一個節點可以在圖中扮演多個不同的角色,因此Neo4j允許我們向一個節點添加多個標籤。

通過這種方式使用標籤,我們可以對節點進行分組。 例如,我們可以要求數據庫查找所有標記爲User的節點。 (標籤也爲聲明式索引節點提供了一個鉤子,我們將在後面看到。)在本書的其餘示例中,我們將廣泛使用標籤。 在節點代表用戶的地方,我們添加了用戶標籤; 在代表訂單的位置,我們添加了“訂單”標籤,依此類推。 我們將在下一章中解釋語法。

圖中的關係自然形成路徑。 查詢或遍歷該圖涉及以下路徑。 由於數據模型的本質是面向路徑的,因此大多數基於路徑的圖數據庫操作與數據的佈局方式高度一致,從而使其極爲高效。 Partner和Vukotic在他們的《行動中的Neo4j》一書中使用關係商店和Neo4j進行了實驗。 比較表明,圖數據庫(在本例中爲Neo4j及其遍歷框架)比關係存儲要快得多。

Partner和Vukotic的實驗旨在在社交網絡中找到朋友的朋友,最大深度爲5。 對於包含1,000,000人(每個人約有50個朋友)的社交網絡,結果強烈表明,圖數據庫是連接數據的最佳選擇,如表2-1所示。

表2-1. 在關係數據庫中查找擴展的朋友與Neo4j中的有效查找

在第二層(朋友的朋友),關係數據庫和圖形數據庫的性能都足夠好,我們可以考慮在在線系統中使用它們。 儘管Neo4j查詢的運行時間是關係查詢的三分之二,但最終用戶幾乎不會注意到兩者之間的毫秒差。 但是,到了深度三(朋友的朋友的朋友)時,很明顯,關係數據庫不再能夠在合理的時間範圍內處理查詢:完成這30秒將完全 在線系統無法接受。 相比之下,Neo4j的響應時間仍然相對平穩:執行查詢只需幾分之一秒,對於在線系統而言絕對足夠快。

在深度四處,關係數據庫表現出嚴重的延遲,這使其幾乎對在線系統毫無用處。 Neo4j的時間安排也略有惡化,但是延遲在響應型在線系統可接受的範圍之內。最後,在第5層深度,關係數據庫僅花費太長時間來完成查詢。 相反,Neo4j在大約兩秒鐘內返回結果。 在深度5,事實證明幾乎整個網絡都是我們的朋友。 因此,對於許多實際使用案例,我們可能會調整結果,從而減少時間。

當我們遠離大小適中的集合操作(它們都應該擅長的操作)時,聚合存儲和關係數據庫的性能都較差。 當我們嘗試從圖中挖掘路徑信息時,事情就變慢了,就像“朋友的朋友”的例子一樣。 我們並不是要在綜合商店或關係數據庫上過分強調。 他們在擅長的事情上擁有出色的技術血統,但是在管理連接的數據時卻不足。 由於所涉及的索引查找次數衆多,因此除了緩慢遍歷直系朋友或可能的親友之外,其他所有操作都將很慢。 另一方面,圖形使用無索引的鄰接關係來確保遍歷連接的數據非常快。

社交網絡示例有助於說明不同的技術如何處理連接的數據,但這是有效的用例嗎? 我們真的需要找到這樣的偏遠的“朋友”嗎? 也許不是。 但是,用其他任何域替換社交網絡,您都會看到我們在性能,建模和維護方面都享有類似的好處。 無論是音樂或數據中心管理,生物信息學或足球統計數據,網絡傳感器還是交易時間序列,圖表都可以爲我們的數據提供強大的洞察力。 然後,讓我們看一下圖表的另一種當代應用:根據用戶的購買歷史以及他的朋友,鄰居和其他類似他的歷史來推薦產品。 在此示例中,我們將彙總用戶生活方式的幾個獨立方面,以提供準確且有利可圖的建議。

首先,將用戶的購買歷史記錄建模爲關聯數據。 在圖形中,這就像將用戶鏈接到她的訂單,然後將訂單鏈接在一起以提供購買歷史記錄一樣簡單,如圖2-6所示。

圖2-6中顯示的圖形提供了對客戶行爲的大量洞察。 我們可以看到用戶已下訂單的所有訂單,並且我們可以輕鬆推斷每個訂單包含哪些內容。 然後,在此核心域數據結構中,我們添加了對幾種知名訪問模式的支持。 例如,用戶經常想查看他們的訂單歷史記錄,因此我們在圖表中添加了一個鏈接列表結構,使我們可以通過遵循傳出的MOST_RECENT關係來查找用戶的最新訂單。 然後,我們可以通過跟蹤每個上一個關係來遍歷列表,以進一步追溯到上一個列表。 如果我們想及時前進,我們可以沿相反的方向遵循每個上一個關係,或者添加一個互惠的下一個關係。

現在我們可以開始提出建議了。 如果我們發現許多購買草莓冰淇淋的用戶也購買了特濃咖啡,那麼我們可以開始向那些通常只購買冰淇淋的用戶推薦這些咖啡豆。 但這是一個一維的建議:我們可以做得更好。 爲了增加圖表的功能,我們可以將其加入其他域的圖表。 由於圖自然是多維結構,因此直接詢問更復雜的數據問題就可以直接進入經過微調的細分市場。 例如,我們可以要求該圖爲我們找到“那些喜歡濃咖啡但不喜歡抱子甘藍並且生活在某個街區的人們喜歡的所有冰淇淋口味”。

爲了解釋數據,我們可以考慮某人重複購買某種產品的程度來表明他們是否喜歡該產品。 但是,我們如何定義“住在附近”呢? 好吧,事實證明,地理空間座標非常方便地建模爲圖形。 用於表示地理空間座標的最受歡迎的結構之一稱爲R-Tree。R-Tree是一種類似圖形的索引,它描述了地理周圍的有界框。 使用這種結構,我們可以描述重疊的位置層次結構。 例如,我們可以表示一個事實,即倫敦在英國,而郵政編碼SW111BD在英國的東南部倫敦,又是英國的倫敦的特特西。 而且由於英國郵政編碼是細粒度的,因此我們可以使用該邊界來定位具有相似品味的人羣。

這種模式匹配查詢在SQL中極難編寫,並且很難對聚合存儲進行編寫,並且在兩種情況下,它們的性能都非常差。 另一方面,圖形數據庫針對這些類型的遍歷和模式匹配查詢進行了優化,在許多情況下可提供毫秒級的響應。 而且,大多數圖數據庫提供適合於表達圖構造和圖查詢的查詢語言。 在下一章中,我們將介紹Cypher,這是一種模式匹配語言,已根據我們傾向於使用圖表來描述圖形的方式進行了調整。

我們可以使用示例圖向用戶提出建議,但也可以使用它使賣方受益。 例如,給定某些購買模式(產品,典型訂單的成本等),我們可以確定特定交易是否具有欺詐性。 可以輕鬆地在圖形中檢測到給定用戶超出規範的模式,然後將其標記出來以引起進一步關注(使用圖形數據挖掘文獻中的衆所周知的相似性度量),從而降低了賣方的風險。

從數據從業者的角度來看,很明顯,圖形數據庫是處理複雜,可變結構,密集連接的數據的最佳技術,也就是說,數據集是如此複雜,以圖形以外的任何形式處理時都不方便。

4.摘要

在本章中,我們瞭解了關係數據庫和NOSQL數據存儲中的連接性如何要求開發人員在應用程序層中實現數據處理,並與圖數據庫進行了對比,在圖數據庫中,連接性是一等公民。 關於圖形建模的更多詳細信息。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章