JanusGraph采用鄰接表(adjacency list
)的方式存儲圖,也即圖以頂點(vertex)和其鄰接表組成。鄰接表中保存某個頂點的所有入射邊(incident edges)。
通過將圖采用鄰接表的形式存儲,JanusGraph確保了某個頂點的所有入射邊和屬性都被緊湊的存儲在一起,從而能夠加快遍歷速度,缺點是數據存儲了兩次。而且JanusGraph以sort key指定的順序存儲數據。
JanusGraph可以采用任何支持big table數據模型的存儲后端存儲鄰接表。
Bigtable Data Model
在Bigtable data model下,表就是行的集合。每個行都唯一的由一個key標識,每行由大量的cell組成。一個cell是由列和值組成的。一個cell唯一的由指定行的制定列所標識。行在bigtable模型中稱為“寬行”,表因此稱為“寬表”。cell的數量可以非常大,而且不需要預定義。
JanusGraph對bigtable數據模型有一個特殊的要求:cell必須是根據列來排序的,而且由column制定的cell的子集必須可以高效查詢。
而且,如果bigtable實現可以根據行的key排序,JanusGraph則可以利用該特性實現更高的圖遍歷性能。
JanusGraph Data Layout
JanusGraph將每個鄰接表作為以個row保存在存儲后端,64位的vertex id是指向鄰接表的key。每個邊和屬性都是作為獨立的cell保存的,以實現更高效插入和刪除。沒行中最大能保存的cell的個數,也就是vertex的edge的數量限制。
Individual Edge Layout
每個edge和property都作為鄰接表的一個cell存儲,並通過序列化之后,byte order即表示了edge label的sort key。variableid對schema進行編碼和壓縮來節省空間。上圖中深藍色的色塊表示了對schema進行編碼壓縮后的ID,用以減少存儲消耗。紅色快代碼一個或多個屬性值,該值也被壓縮並關聯到屬性key上。灰色塊代表未壓縮的屬性值,如(序列化的OBJECT)。
Edge有edge label唯一ID開始,並附加一個表示方向的數據位;之后有屬性key組成的排序鍵,再之后是鄰接表IDD,和邊ID。Janus並不保存實際的vertex id,而是相對於鄰接表的偏移量,因其比壓縮更節省空間。value部分保存了序列化后的值。
對於屬性來說就簡單一點,column是屬性的key id,property id和property key保存在value部分,如果property key被定義為LIST,property id也保存在列中。
總結
對於理解JanusGraph的存儲,關鍵在於理解其bigtable的鄰接表存儲結構,而在鄰接表中保存了邊(包括邊的屬性)及vertex的屬性。
由於邊是由兩個vertex定義的,故肯定存在有edge的重復保存,這增加了存儲空間,但通過冗余也提高了查詢效率。
最后是每個鄰接表:行,的數據結構,對於一般的應用場景,我們沒有必要深入到行存儲中去,只是了其存儲的一般原理即可。
