开发 Arrow C++ 计算模块#

本节为 Arrow C++ 计算模块的开发者提供相关信息。

行表 (Row Table)#

Arrow 中的行表以行优先 (row-major) 格式存储数据。这种格式对于涉及随机访问单行数据,以及需要频繁同时访问所有列的场景特别有用。它对于哈希表键值尤为有利,并通过优化内存访问模式和数据局部性,促进了分组和哈希连接等高效操作。

元数据#

行表由其元数据 RowTableMetadata 定义,其中包括关于其模式 (schema)、对齐方式和派生属性的信息。

模式指定了列的类型和顺序。行表中的每一行都包含按该逻辑顺序排列的各列数据(物理顺序可能有所不同;详见 行编码)。

注意

行表中支持嵌套类型或大二进制类型的列。

从模式中导出的一个重要属性是行表是定长还是变长的。定长行表仅包含定长列,而变长行表至少包含一个变长列。这种区别决定了数据在行表中的存储和访问方式。

行表中的每一行都与 RowTableMetadata::row_alignment 字节对齐。长度非 2 的幂的定长列也与 RowTableMetadata::row_alignment 字节对齐。变长列则与 RowTableMetadata::string_alignment 字节对齐。

缓冲区布局#

与大多数 Arrow Array 类似,行表由三个缓冲区组成:

  • 空值掩码缓冲区 (Null Masks Buffer):指示每一行中每一列的空值情况。

  • 定长缓冲区 (Fixed-length Buffer):存储定长表中的行数据,或存储变长表中指向变长数据的偏移量。

  • 变长缓冲区 (Varying-length Buffer)(可选):包含变长表中的行数据;对于定长表,此缓冲区不使用。

行格式#

空值掩码#

对于每一行,用连续的位序列表示该行中的每一列是否为空。每一位对应一列,1 表示值为空,0 表示值为有效。注意,这与 Array 的有效性位图(validity bitmap)逻辑相反。一行的空值掩码占用 RowTableMetadata::null_masks_bytes_per_row 字节。

定长行数据#

在定长行表中,行数据直接存储在定长缓冲区中。每一行中的所有列依次存储。值得注意的是,boolean 列比较特殊:在普通 Arrow Array 中它占用 1 位,而在行表中它占用 1 字节。变长缓冲区在这种情况下不使用。

例如,模式为 (int32, boolean) 且行为 [[7, false], [8, true], [9, false], ...] 的行表,在定长缓冲区中存储如下:

第 0 行

第 1 行

第 2 行

7 0 0 0, 0 (填充)

8 0 0 0, 1 (填充)

9 0 0 0, 0 (填充)

变长行数据的偏移量#

在变长行表中,定长缓冲区包含指向变长行数据的偏移量,变长数据单独存储在可选的变长缓冲区中。偏移量类型为 RowTableMetadata::offset_type(固定为 int64_t),指示每一行数据的起始位置。

变长行数据#

在变长行表中,变长缓冲区包含实际的行数据,数据连续存储。定长缓冲区中的偏移量指向每一行数据的起始位置。

行编码#

变长行的编码方式如下:

  • 首先存储定长列。

  • 接着是每个变长列的偏移量序列。每个偏移量为 32 位,指示对应变长列在行数据内的结束位置。

  • 最后存储变长列。

例如,模式为 (int32, string, string, int32) 且行为 [[7, 'Alice', 'x', 0], [8, 'Bob', 'y', 1], [9, 'Charlotte', 'z', 2], ...] 的行表,存储如下(假设变长列为 8 字节对齐):

定长缓冲区(行偏移量)

第 0 行

第 1 行

第 2 行

第 3 行

0 0 0 0 0 0 0 0

32 0 0 0 0 0 0 0

64 0 0 0 0 0 0 0

104 0 0 0 0 0 0 0

变长缓冲区(行数据)

定长列

变长偏移量

变长列

0

7 0 0 0, 0 0 0 0

21 0 0 0, 25 0 0 0

Alice~~~x~~~~~~~

1

8 0 0 0, 1 0 0 0

19 0 0 0, 25 0 0 0

Bob~~~~~y~~~~~~~

2

9 0 0 0, 2 0 0 0

25 0 0 0, 33 0 0 0

Charlotte~~~~~~~z~~~~~~~

3