随着 2.0 各版本的陆续发布,Nebula Graph 迎来了一系列的改动,在存储方面,影响最大的改动就是底层编码格式进行了修改。Nebula Graph 的底层存储是基于 KV 保存在 RocksDB 中,本文将介绍新老编码格式的差别,以及为何要修改存储格式等一系列问题。git
咱们先简单回顾下 1.0 版本的编码格式,不熟悉的能够参考这篇博客《Nebula 架构剖析系列(一)图数据库的存储设计》。因为在 1.0 版本中,点的 ID 只可以用整型来表示,因此底层全部 VertexID 都是以 int64 来保存的。github
给定任何一个 VertexID,通过 hash,能够获得对应的 PartID,所以对于一个点和这个点的全部边(边用起点计算 hash),都会映射到同一个分片中。须要指出的是,在 1.0 版本中,点和边的第一个字节的 Type 是相同的。也就是说,对于一个点而言,它的全部 tag 并无在物理上连续保存,好比多是以下保存的。对于这个 src 这个点的三个 tag(tag1 tag2 tag3),实际上可能会被其余边隔开。数据库
这个格式可以知足 1.0 绝大多数接口的须要,好比 fetch
和 go
都只须要指定对应前缀,就能获取对应数据。微信
在 GA 以前发布的版本,底层存储格式其实和 1.0 是基本相同的。若是 VertexID 是整型,和 1.0 格式彻底一致。而若是 VertexID 类型支持 string,则从占用 8 个字节的 int64 改为了固定长度的 FIXED_STRING
,长度须要用户在 create space
时候指定长度。对于不足的长度系统自动使用 \0
补齐,而超过指定长度的 VertexID 会直接报错。架构
在 GA 版本中,咱们对底层存储格式进行了若干改动,所以此次版本升级时须要经过升级工具,将原有格式的数据转换为新格式的数据。以下是在 2.0 GA 版本中采用的存储格式。ide
其中有几个比较大的改动:工具
这些改动主要是基于如下几点进行考虑的:post
为何 string ID 要使用 FIXED_STRING ? 若是不使用固定长度,则没法使用前缀进行扫描。经过长度不足补齐,使得全部点之间和边之间的各个前缀长度相同,从而进行相应的前缀查询。性能
在边里面还保留一个字节的占位符,主要是留给 TOSS(transaction on storage side)使用。主要用于标识一条边的出边和入边是否完整插入了,这里不详细介绍,后续会有其余文章进行详尽的分析。fetch
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 拉你进交流群~~