Nebula Storage 2.0 存儲格式

storage-format-in-nebula-graph-2.0

隨着 2.0 各版本的陸續發佈,Nebula Graph 迎來了一系列的改動,在存儲方面,影響最大的改動就是底層編碼格式進行了修改。Nebula Graph 的底層存儲是基於 KV 保存在 RocksDB 中,本文將介紹新老編碼格式的差別,以及爲何要修改存儲格式等一系列問題。git

1.0 版本的格式

咱們先簡單回顧下 1.0 版本的編碼格式,不熟悉的能夠參考這篇博客《Nebula 架構剖析系列(一)圖數據庫的存儲設計》。因爲在 1.0 版本中,點的 ID 只可以用整型來表示,因此底層全部 VertexID 都是以 int64 來保存的。github

  • 點的格式

Nebula Graph 1.0 點的格式

  • 邊的格式

Nebula Graph 1.0 邊的格式

給定任何一個 VertexID,通過 hash,能夠獲得對應的 PartID,所以對於一個點和這個點的全部邊(邊用起點計算 hash),都會映射到同一個分片中。須要指出的是,在 1.0 版本中,點和邊的第一個字節的 Type 是相同的。也就是說,對於一個點而言,它的全部 tag 並無在物理上連續保存,好比多是以下保存的。對於這個 src 這個點的三個 tag(tag1 tag2 tag3),實際上可能會被其餘邊隔開。數據庫

rocksdb key 存儲

這個格式可以知足 1.0 絕大多數接口的須要,好比 fetchgo 都只須要指定對應前綴,就能獲取對應數據。微信

2.0 版本的格式

在 GA 以前發佈的版本,底層存儲格式其實和 1.0 是基本相同的。若是 VertexID 是整型,和 1.0 格式徹底一致。而若是 VertexID 類型支持 string,則從佔用 8 個字節的 int64 改爲了固定長度的 FIXED_STRING,長度須要用戶在 create space 時候指定長度。對於不足的長度系統自動使用 \0 補齊,而超過指定長度的 VertexID 會直接報錯。markdown

在 GA 版本中,咱們對底層存儲格式進行了若干改動,所以此次版本升級時須要經過升級工具,將原有格式的數據轉換爲新格式的數據。以下是在 2.0 GA 版本中採用的存儲格式。架構

2.0 版本存儲格式

  • 點的格式

Nebula Graph 2.0 點的格式

  • 邊的格式

Nebula Graph 2.0 邊的格式

和 1.0 存儲格式對比

點格式版本對比

點格式版本對比

其中有幾個比較大的改動:ide

  1. VertexID 的長度如前文所說,從固定的 8 字節,修改成 n 個字節。VertexID 類型爲整型時,n 爲 8,VertexID 類型爲 string 類型時,n 爲指定長度。
  2. 點去掉了 1.0 的時間戳。邊將 1.0 時間戳改成了一個字節的佔位符。
  3. 對於點和邊的第一個字節,再也不使用同一個 Type,在物理上點和邊進行了分離。

這些改動主要是基於如下幾點進行考慮的:工具

  1. VertexID 改變主要是爲了支持 string ID 同時兼容 1.0 版本 int ID。在 storage 中,把 VertexID 都處理爲 bytes,只在返回結果時根據 space 的設置不一樣,返回相應類型的 VertexID。

    爲何 string ID 要使用 FIXED_STRING ? 若是不使用固定長度,則沒法使用前綴進行掃描。經過長度不足補齊,使得全部點之間和邊之間的各個前綴長度相同,從而進行相應的前綴查詢。oop

  2. 去掉時間戳主要是由於保存多版本數據會影響性能,另一段時間內暫時不考慮作 MVCC 的相關工做。

    在邊裏面還保留一個字節的佔位符,主要是留給 TOSS(transaction on storage side)使用。主要用於標識一條邊的出邊和入邊是否完整插入了,這裏不詳細介紹,後續會有其餘文章進行詳盡的分析。post

  3. 點和邊分離的好處主要是可以方便快速拿某個點的全部 tag(在Cypher 的 MATCH 語句中大量使用)。若是按原先同一 Type + VertexID 前綴掃描,因爲點邊可能摻雜在一塊兒,會極大影響性能。而 Type 分離以後,按 VertexType + VertexID 前綴掃描,能夠快速獲取全部 tag。

    在 1.0 版本中,因爲沒有取某個點的全部 tag 的需求,所以點和邊能夠按同一個前綴保存。不過在代碼層面,仍是有不小影響,例如 fetch 接口在 1.0 是按 VertexID 的前綴去掃描的,對於超級大點來講取 tag 性能比較差。另外若是使用 storage 提供的 scan 接口,想要獲取全圖的全部點,實際是掃描了整個 RocksDB。

除了點和邊的格式相關改動以外,索引的格式其實也有所改變。

一方面是 2.0 支持 NULL 後,索引也須要可以表示對應的語義。另外一方面是在 1.0 的版本中,對於索引中 string 的字段的處理,實際是按變長 string 處理。所以在 LOOKUP 語句中只要使用了帶 string 字段的索引,就只能使用等值查詢。而在 2.0 的版本中,索引的 string 字段和數據中的 VertexID 同樣,使用固定長度的 FIXED_STRING,LOOKUP 語句中帶 string 字段的索引可以使用範圍查詢,例如 LOOKUP ON index1 WHERE col > "aaa"。有關索引部分的功能和修改,後續也會再有其餘文章介紹。

以上,爲本次 Nebula Storage 2.0 存儲格式講解。

喜歡這篇文章?來來來,給咱們的 GitHub 點個 star 表鼓勵啦~~ 🙇‍♂️🙇‍♀️ [手動跪謝]

交流圖數據庫技術?交個朋友,Nebula Graph 官方小助手微信:NebulaGraphbot 拉你進交流羣~~

推薦閱讀

相關文章
相關標籤/搜索