Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Explain storage format change #1503

Merged
merged 3 commits into from
Feb 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -70,47 +70,38 @@ Nebula Graph 使用自行开发的 KVStore,而不是其他开源 KVStore,原

- 支持多个图空间,不同图空间相互隔离,每个图空间可以设置自己的分片数和副本数。

<!--
## 数据存储格式

图存储的主要数据是点和边,Nebula Graph 将点和边的信息存储为 key,同时将点和边的属性信息存储在 value 中,以便更高效地使用属性过滤。

由于 Nebula Graph 2.0 的数据存储格式在 1.x 的基础上做了修改,下文将在介绍数据存储格式时同时介绍不同版本的差异。

- 点数据存储格式

![The vertex format of storage service](https://www-cdn.nebula-graph.com.cn/nebula-blog/nebula-graph-vertex-data-format.png)
相比 Nebula Graph 2.x 版本,3.x 版本的每个点多了一个不含 TagID 字段并且无 value 的 key,用于支持无 Tag 的点。

![The vertex format of storage service](3.0-vertex-key.png)

|字段|说明|
|:---|:---|
|`Type`|key 类型。长度为 1 个字节。|
|`PartID`|数据分片编号。长度为 3 个字节。此字段主要用于 Storage 负载均衡(balance)时方便根据前缀扫描整个分片的数据。|
|`VertexID`|点 ID。当点 ID 类型为 int 时,长度为 8 个字节;当点 ID 类型为 string 时,长度为创建图空间时指定的`fixed_string`长度。|
|`TagID`|点关联的 Tag ID。长度为 4 个字节。|
|`Type`|key 类型。长度为 1 字节。|
|`PartID`|数据分片编号。长度为 3 字节。此字段主要用于 Storage 负载均衡(balance)时方便根据前缀扫描整个分片的数据。|
|`VertexID`|点 ID。当点 ID 类型为 int 时,长度为 8 字节;当点 ID 类型为 string 时,长度为创建图空间时指定的`fixed_string`长度。|
|`TagID`|点关联的 Tag ID。长度为 4 字节。|
|`SerializedValue`|序列化的 value,用于保存点的属性信息。|

- 边数据存储格式

![The edge format of storage service](https://www-cdn.nebula-graph.com.cn/nebula-blog/nebula-graph-edge-data-format.png)
![The edge format of storage service](3.0-edge-key.png)

|字段|说明|
|:---|:---|
|`Type`|key 类型。长度为 1 个字节。|
|`PartID`|数据分片编号。长度为 3 个字节。此字段主要用于 Storage 负载均衡(balance)时方便根据前缀扫描整个分片的数据。|
|`VertexID`|点 ID。前一个`VertexID`在出边里表示起始点 ID,在"入边"里表示目的点 ID;后一个`VertexID`"出边"里表示目的点 ID,在"入边"里表示起始点 ID。|
|`Edge type`|边的类型。大于 0 表示"出边",小于 0 表示"入边"。长度为 4 个字节。|
|`Rank`|用来处理两点之间有多个同类型边的情况。用户可以根据自己的需求进行设置,例如存放交易时间、交易流水号等。长度为 8 个字节,|
|`PlaceHolder`|预留。长度为 1 个字节。|

!!! compatibility "历史版本兼容性"

2.0 和 1.x 的差异如下:

- 1.x 中,点和边的`Type`值相同,而在 2.0 中进行了区分,即在物理上分离了点和边,方便快速查询某个点的所有 Tag。
- 1.x 中,`VertexID`仅支持 int 类型,而在 2.0 中新增了 string 类型。
- 2.0 中取消了 1.x 中的保留字段`Timestamp`。
- 2.0 中边数据新增字段`PlaceHolder`。
- 2.0 中修改了索引的格式,以便支持范围查询。
-->
|`Type`|key 类型。长度为 1 字节。|
|`PartID`|数据分片编号。长度为 3 字节。此字段主要用于 Storage 负载均衡(balance)时方便根据前缀扫描整个分片的数据。|
|`VertexID`|点 ID。前一个`VertexID`在出边里表示起始点 ID,在入边里表示目的点 ID;后一个`VertexID`出边里表示目的点 ID,在入边里表示起始点 ID。|
|`Edge type`|边的类型。大于 0 表示出边,小于 0 表示入边。长度为 4 字节。|
|`Rank`|用来处理两点之间有多个同类型边的情况。用户可以根据自己的需求进行设置,例如存放交易时间、交易流水号等。长度为 8 字节,|
|`PlaceHolder`|预留字段。长度为 1 字节。|
|`SerializedValue`|序列化的 value,用于保存边的属性信息。|

### 属性说明

Nebula Graph 使用强类型 Schema。
Expand All @@ -123,29 +114,28 @@ Nebula Graph 使用强类型 Schema。

![data partitioning](https://www-cdn.nebula-graph.com.cn/nebula-blog/DataModel02.png)

<!--
### 切边与存储放大

Nebula Graph 中逻辑上的一条边对应着硬盘上的两个键值对(key-value pair),在边的数量和属性较多时,存储放大现象较明显。边的存储方式如下图所示。

![edge storage](https://docs-cdn.nebula-graph.com.cn/docs-2.0/1.introduction/2.nebula-graph-architecture/two-edge-format.png)
![edge storage](edge-division.png)

上图以最简单的两个点和一条边为例,起点 SrcVertex 通过边 EdgeA 连接目的点 DstVertex,形成路径`(SrcVertex)-[EdgeA]->(DstVertex)`。这两个点和一条边会以 4 个键值对的形式保存在存储层的两个不同分片,即 Partition x 和 Partition y 中,详细说明如下:
上图以最简单的两个点和一条边为例,起点 SrcVertex 通过边 EdgeA 连接目的点 DstVertex,形成路径`(SrcVertex)-[EdgeA]->(DstVertex)`。这两个点和一条边会以 6 个键值对的形式保存在存储层的两个不同分片,即 Partition x 和 Partition y 中,详细说明如下:

* 点 SrcVertex 的键值保存在 Partition x 中。Key 的字段有 Type、PartID(x),VID(Src)和 TagID。SerializedValue 即 Value,是序列化的点属性。
* 点 SrcVertex 的键值保存在 Partition x 中。

* EdgeA 的第一份键值,这里用 EdgeA_Out 表示,与 SrcVertex 一同保存在 Partition x 中。Key 的字段有 Type、PartID(x)、VID(Src,即点 SrcVertex 的 ID)、EdgeType(符号为正,代表边方向为出)、Rank(0)、VID(Dst,即点 DstVertex 的 ID)和 PlaceHolder。SerializedValue 即 Value,是序列化的边属性。
* EdgeA 的第一份键值,这里用 EdgeA_Out 表示,与 SrcVertex 一同保存在 Partition x 中。key 的字段有 Type、PartID(x)、VID(Src,即点 SrcVertex 的 ID)、EdgeType(符号为正,代表边方向为出)、Rank(0)、VID(Dst,即点 DstVertex 的 ID)和 PlaceHolder。SerializedValue 即 Value,是序列化的边属性。

* 点 DstVertex 的键值保存在 Partition y 中。Key 的字段有 Type、PartID(y),VID(Dst)和 TagID。SerializedValue 即 Value,是序列化的点属性。
* 点 DstVertex 的键值保存在 Partition y 中。

* EdgeA 的第二份键值,这里用 EdgeA_In 表示,与 DstVertex 一同保存在 Partition y 中。Key 的字段有 Type、PartID(y)、VID(Dst,即点 DstVertex 的 ID)、EdgeType(符号为负,代表边方向为入)、Rank(0)、VID(Src,即点 SrcVertex 的 ID)和 PlaceHolder。SerializedValue 即 Value,是序列化的边属性,与 EdgeA_Out 中该部分的完全相同。
* EdgeA 的第二份键值,这里用 EdgeA_In 表示,与 DstVertex 一同保存在 Partition y 中。key 的字段有 Type、PartID(y)、VID(Dst,即点 DstVertex 的 ID)、EdgeType(符号为负,代表边方向为入)、Rank(0)、VID(Src,即点 SrcVertex 的 ID)和 PlaceHolder。SerializedValue 即 Value,是序列化的边属性,与 EdgeA_Out 中该部分的完全相同。

EdgeA_Out 和 EdgeA_In 以方向相反的两条边的形式存在于存储层,二者组合成了逻辑上的一条边 EdgeA。EdgeA_Out 用于从起点开始的遍历请求,例如`(a)-[]->()`;EdgeA_In 用于指向目的点的遍历请求,或者说从目的点开始,沿着边的方向逆序进行的遍历请求,例如例如`()-[]->(a)`。

如 EdgeA_Out 和 EdgeA_In 一样,Nebula Graph 冗余了存储每条边的信息,导致存储边所需的实际空间翻倍。因为边对应的 Key 占用的硬盘空间较小,但 Value 占用的空间与属性值的长度和数量成正比,所以,当边的属性值较大或数量较多时候,硬盘空间占用量会比较大。
如 EdgeA_Out 和 EdgeA_In 一样,Nebula Graph 冗余了存储每条边的信息,导致存储边所需的实际空间翻倍。因为边对应的 key 占用的硬盘空间较小,但 value 占用的空间与属性值的长度和数量成正比,所以,当边的属性值较大或数量较多时候,硬盘空间占用量会比较大。

如果对边进行操作,为了保证两个键值对的最终一致性,可以开启 [TOSS 功能](../../5.configurations-and-logs/1.configurations/3.graph-config.md),开启后,会先在正向边所在的分片进行操作,然后在反向边所在分片进行操作,最后返回结果。
-->

### 分片算法

分片策略采用**静态 Hash **的方式,即对点 VID 进行取模操作,同一个点的所有 Tag、出边和入边信息都会存储到同一个分片,这种方式极大地提升了查询效率。
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.