在選擇數據庫的路上,咱們遇到過哪些坑?(2)

【編者按】你會怎麼選擇數據庫,是關係數據庫、XML 數據庫、資源描述框架(RDF),仍是圖形數據庫?本文的第1部分深刻而生動地探討了各類選擇。在第2部分,將深刻介紹使用 Neo4j 的注意點。文章系國內 ITOM 管理平臺 OneAPM 編譯呈現。html

##過渡到 Neo4j 以後的經驗和教訓 下面介紹一些有關運行 Neo4j 的實用技巧:數據庫

###1. 若是你是 Java 商城,請嵌入式地運行 Neo4j Neo4j 是本地 Java 平臺,咱們又是 Java 商城,用 Neo4j 至關合適。嵌入 Neo4j 讓咱們不用再進行 REST 調用,這對於安全來講確實很重要。有關進行 REST 調用的進一步危害,請觀看這段有關 REST 安全漏洞的 JavaOne 討論api

嵌入式地運行 Neo4j 還爲咱們大幅下降了複雜性。咱們能夠直接在進程中調用 Neo4j API,從而快速瞭解 Cypher 語言,以便運行 Cypher 和 Java API 這二者的結合體。同時咱們不再須要託管和非託管的擴展了。緩存

##2. 摸清本身的優點 摸清本身的優點和所選擇的工具的優點,這一點極爲重要。用工具來作不適當的事,效果會大打折扣。安全

本地圖形數據庫在關係方面的表現確實很好;在圖形中找到切入點,而後按照須要深刻地研究各類關係,這在 Neo4j 中快得驚人。但若是想要在單個節點以外進行復雜的多值屬性全文檢索,效果就大打折扣了 —— 但咱們選擇圖形數據庫並非爲了作這個。服務器

##3. 瞭解查詢時會發生哪些事情 瞭解查詢時會發生哪些事情,這一點也極爲重要,這可以優化 Cypher 語言。框架

請看下面這個很是簡單的查詢。我想要找到 Franklin Country 全部擁有狩獵執照的男性,而且執照上的地址須要和此人的家庭住址相匹配,以便咱們確認這是同一我的。工具

我有一我的員節點,一個執照節點,還有一個位置節點,每一個節點上都有各類不一樣屬性:性能

在選擇數據庫的路上,咱們遇到過哪些坑?(2)

數據庫要作的第一件事就是找到切入點(可能有多個切入點),而後圖形從切入點展開搜索。尋找切入點一般是個讓人頭痛的問題。爲此要使用帶有靜態索引集的基於規則的規劃程序,這一軟件已於近期升級爲基於費用。這雖然還不夠完美,但無疑已經朝着正確的方向前進了一大步。優化

###索引

索引基本上會複製數據庫中的信息片斷,這樣有利於它迅速找到節點。在本例中,只使用信息片斷來肯定切入點。雖然不是必需要使用索引,但它確實能派上用場。若是要在特定的節點屬性上進行檢索,在節點上設置一個索引會是個好辦法,即便這會佔用磁盤空間。

索引分爲兩種:schema 和 legacy。Schema 索引是最新版,使用內部自定義的 Neo4j 內置索引,目前是默認設置。

一旦利用 Cypher 或 Java API 建立 schema 索引後,這些索引就會自動由數據庫維護。例如,若是你想在每一個帶有「人員」標籤和「性別」屬性的節點上建立索引,當你建立新節點、更改節點值或刪除節點時,數據庫將自動對其進行更新。這時你也能夠設置限定條件,好比必須存在屬性或屬性必須是惟一的。

Legacy 索引是 Lucene 索引,是較早的版本但還沒有棄用。能夠經過配置文件、Neo4j 屬性文件、Java API 或 Cypher 來設置 legacy 索引。Legacy 索引使用的是 Lucene 而非 Neo4j 專有索引機制。咱們在用 Neo4j 時幾乎沒有什麼漏洞,而每次遇到的漏洞基本都和 legacy 索引有關。即便是這樣,有時候這些索引也是必要的。

Apache Luke 是一款很是不錯的開源工具,用戶能夠用它直接查看和搜索 Lucene 索引。這也幫助咱們修復了 legacy 索引中的異常行爲。

###自動索引與手動索引

Legacy 索引有兩種用法:自動索引和手動索引。我建議使用自動索引,由於它更容易維護。基本上只要設置一次(能夠在配置文件中設置也能夠經過 API 設置),而後設爲在特定類型的節點上爲特定類型的屬性編寫索引。自動索引還可以在必要時輕鬆重建索引。

可是用戶沒法指定是哪一種類型的索引。在 Lucene 中,schema 存在不一樣索引類型,例如字符串、區分大小寫,以及數值,這些都是物理上獨立的索引。

若是你在查詢 Lucene 時想要使用這些索引,必需要作的第一件事就是告訴 Lucene 要使用哪一個索引。但若是進行自動索引,Neo4j 能夠根據你要編寫索引的第一個對象來選擇使用哪一個索引。例如,若是你設置的第一個索引是藍色,Neo4j 就會明白藍色是字符串,而後會永久性地將藍色放在字符串索引中。

若是你能很好地控制收到的數據,這一索引方式效果會很不錯。但咱們的系統沒有這樣。咱們從許多不一樣的來源接收數據,因此收到的「blue」(藍色)屬性可能會指年齡。但若是這一屬性是最早收到的,Neo4j 就會把年齡做爲基於字符串的屬性而不是數值屬性來編寫索引,如此一來,以後就無法按照我但願的方式展開進一步比對和排列了。在這種狀況下,只能手動建立索引。

使用自動索引的另外一個好處是,若是目錄無端損壞,很容易就能修復目錄。能夠暫停整個數據庫,進入 Lucene 索引目錄,刪除此目錄,重啓數據庫,而後 Neo4j 會爲全部節點從新編寫索引。但若是已經進行了手動索引,你只能返回,而後爲全部節點從新編寫索引。

###範圍查詢

下面一系列幻燈片顯示了範圍查詢:

在選擇數據庫的路上,咱們遇到過哪些坑?(2)

我想查詢「profile」(我的信息),因此我把 PROFILE 放在查詢內容的前面。我想找到收入爲特定數值(50500)的全部人羣而且只返回最前面的兩個結果。

這段代碼代表,我已經有了某人的收入索引,規劃程序的限值是 2。NodeIndexSeek 用這一索引來查找數值,從一個擁有 22 萬人的樣本數據庫中進行了大約 2800 次數據庫訪問。

在接下來的範圍查詢中,我準備查找收入低於 50500 的人:

在選擇數據庫的路上,咱們遇到過哪些坑?(2)

在此次的查詢中,咱們執行了 NodeByLabelScan,因爲沒有使用索引,咱們進行了多達 43 萬次數據庫訪問。在 Neo4j 第 2.3 版以前,schema 索引不支持範圍,因此你必須得用 legacy 索引,而後直接查詢 Lucene 索引,才能發揮做用。

第 2.3 版修復了這一問題;如今有了 NodeIndexSeekByRange,可在 schema 標籤上提供範圍索引:

在選擇數據庫的路上,咱們遇到過哪些坑?(2)

##4. 不要使用內部節點 ID 使用當前節點 ID 是個很大的誘惑,但這種作法很是不可取,這是由於在某些時刻,這種作法會致使數據庫內容被刪除。請閱讀這篇介紹,瞭解更多相關內容。

Neo4j 使用增量日誌。若是你刪除了某個節點,最後系統會翻轉節點 ID,這樣你就能夠重複使用這些數字。咱們結合使用了節點標籤和隨機選擇的 UUID,這樣若是你的 API 始終暴露在外,就能夠提供額外的安全保障。

##5. 數據建模很重要 數據模型的重要程度至少和查詢至關。下面的說明頗有用:能夠經過多重關係類型或關係上的屬性來爲部分關係建模。兩種方法彷佛一樣合理,但它們的性能表現可能截然不同。必定要了解一下 GraphAware 對這一內容的介紹。其區別在於,一方定義不一樣類型的 personplace 之間的關係……

在選擇數據庫的路上,咱們遇到過哪些坑?(2)

……而另外一方則表示有三種不一樣的屬性類型:

在選擇數據庫的路上,咱們遇到過哪些坑?(2)

性能表現提高了八倍。上述 GraphAware 的文章深刻詳細地解釋了這一律念。

##6. 優化性能 EXPLAINPROFILE 絕對是你的良師益友。別擔憂 Java API,而查詢規劃程序還很年輕,在許多狀況下都比 Cypher 要快。若是你要設定基準,必定要以溫備份數據庫設定基準。這樣就能加載 Neo4j 的數據庫緩存。

##7. 必定要交流! Neo4j 擁有強大的支持社區,包括谷歌論壇、Slack 協做頻道、Stack Overflow 網站和很是出色的支持團隊

##8. 在工具欄裏添加下面的代碼 藉助下面的樣板代碼,能夠檢查數據庫中的每一個節點並修復全部問題。這一示例有時會抓取關係,但你也能夠對節點或其餘限定條件進行一樣的操做。

無論怎樣,它都能事務性地依次經過數據庫中的全部節點。在本例中,每一個事務是 90000 次操做,若是有須要,還能夠批量更改整個數據庫:

在選擇數據庫的路上,咱們遇到過哪些坑?(2)

本文系 OneAPM 工程師整理呈現。OneAPM 能爲您提供端到端的應用性能解決方案,咱們支持全部常見的框架及應用服務器,助您快速發現系統瓶頸,定位異常根本緣由。分鐘級部署,即刻體驗,性能監控歷來沒有如此簡單。想閱讀更多技術文章,請訪問 OneAPM 官方技術博客

本文轉自 OneAPM 官方博客

原文地址:https://dzone.com/articles/from-good-to-graph-choosing-the-right-database

相關文章
相關標籤/搜索