Nebula Storage 2.0 存儲格式

storage-format-in-nebula-graph-2.0

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

1.0 版本的格式

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

  • 點的格式

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 會直接報錯。

在 GA 版本中,我們對底層存儲格式進行了若干改動,因此這次版本升級時需要通過升級工具,將原有格式的數據轉換爲新格式的數據。如下是在 2.0 GA 版本中採用的存儲格式。

2.0 版本存儲格式

  • 點的格式

Nebula Graph 2.0 點的格式

  • 邊的格式

Nebula Graph 2.0 邊的格式

和 1.0 存儲格式對比

點格式版本對比

點格式版本對比

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

  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 ? 如果不使用固定長度,則無法使用前綴進行掃描。通過長度不足補齊,使得所有點之間和邊之間的各個前綴長度相同,從而進行相應的前綴查詢。

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

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

  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 拉你進交流羣~~

推薦閱讀

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