大规模数据分析提效|行列混存格式下的读链路优化

引言

在大数据领域,行列混存是主要的存储格式。相较于行存或列存,行列混存在兼顾点查性能的同时,能够通过列裁剪来减少 I/O 和数据解码等开销,提升扫描性能。同时行列混存支持高效的压缩算法,通过将同一列的数据存储在一起提高局部数据的相似性,从而实现更高的压缩比。Relyt AI-ready Data Cloud 实现了类 Parquet 的行列混存格式,同时结合客户需求做了大量的优化工作。

今天,我们邀请质变科技AI-ready 数据云团队布道师北辰为大家分享话题《提升数据处理效率:行列混存格式下的读链路优化》,从数据裁剪和数据编解码两个方面,为大家介绍 Relyt 在读链路上所做的优化工作。

数据裁剪

提升查询链路性能,最直接的做法是减少扫描的数据量,而减少扫描数据量在查询执行的不同阶段有不同的优化手段。在有 ClusterKey 的场景下,Relyt 支持从 MetaService 获取文件列表时就将 ClusterKey 相关 Filter 带入,根据文件级别 ClusterKey 的 Min/Max 信息过滤掉不需要的文件。对于必须读取后才能进行过滤的数据,Relyt 会将部分 Filter 下推为 MetaFilter,在 FileReader 中从 Block 级别和 Page 级别进行粗糙级过滤;而对于延迟物化以及类似包含 DeleteVector 的场景,可以将 Selectivity 下推到解码链路;通过以上这些数据裁剪方式,Relyt 尽可能减少 I/O 和数据解码开销,提升扫描性能。

以下主要从 Block 裁剪、Page 裁剪和 Selectivity 下推三个方面进行介绍。

Block 裁剪

在一个行列混存文件中,Footer 中的文件 Meta 存储了 Block 级别的列级统计信息,主要包含 Min/Max、NullCount 等,其格式如下:

图片

打开文件时,Relyt 首先会从文件 Footer 中获取 Block 级别列的统计信息,结合下推的 MetaFilter 进行表达式计算,得到每一列各自命中的 BlockIndex 。由于各列的数据在 Block 级别按行对齐,在计算最终命中的 Block 时只需要将各列命中的 BlockIndex 结果根据 Filter 逻辑关系取交并差即可,这给 Block 裁剪提供了极大的便利。以下述查询为例:

select * from test where id < 100 and dt between '2024-12-01' and '2024-12-04';

假设一个文件中一共有N(N>4)个 Block,其中命中第 1、3 个 Block , 条件命中第 2、3个 Block :

图片

由于两个查询条件是 And 关系,所以最终命中第 3 个 Block,此时整个文件只需读一个 Block,极大减少了 IO。

此外,Relyt针对文件 Footer 部分元数据做了轻量级 Cache,进一步减少打开文件的开销。

Page 裁剪

考虑到写入性能及数据压缩等多方面影响,Block 通常不会设置得很小(一般 64MB ~ 256MB),导致 Block 裁剪效果有限,不能充分减少 I/O 和不必要的数据解码。因此,Relyt 在 Block 裁剪的基础之上,利用 Page 级别统计信息实现了更细粒度的裁剪。

Relyt中的 Page 是一个 Block 内的 ColumnChunk 按大小进一步切分的产物,Page 级别的统计信息存储在文件 Footer 与数据区之间的一块独立区域,统计信息除包含 Min/Max 等信息外,还记录了当前 Page 中第一行数据在 Block 内的行号、数据在文件中的偏移和长度等信息。各列间的 Page 由于无法保证按行对齐,使得裁剪过程更复杂。当利用 Page 级别统计信息进行过滤时,首先计算出各列命中的 Page,然后根据列间 Filter 逻辑关系计算出多列命中的公共行集,随后根据命中的行集得到各列命中的 Page,最后各列在命中的 Page 内根据行集读具体数据。以下面的查询为例:

select * from test where a = 'x' and b = 'y'

读Block 时,条件命中第 1、3 个 Page , 命中第 0、2 个 Page。如下图所示,可以知道 Column a 命中的行区间为 [1000, 2200) 和 [3000,3990),Column b 命中的行区间为 [0,500) 和 [1500, 3000)。因此,命中的行区间为 [1500, 2200)。根据 [1500, 2200) 及各列的 Page 统计信息,可知该行号区间对应 Column a 第 1 个 Page 的后半部分,Column b 第 2 个 Page 的前半部分。Relyt 中 Page 是最小的解压单位,所以对于 Column a 和 Column b,对应 Page 都需要从 I/O 层完整加载上来,然后根据命中的行区间,各自完成 Page 内“掐头去尾”的工作,并且如果 Page 内多个命中的行集间存在空洞,还需要跳过这些空洞,将列间的数据按行对齐后输出。

图片

在这个过程中,Relyt针对 I/O 操作也做了大量优化,除了常见的 I/O 合并外,还实现了基于固定 Buffer 空间的环形滑动窗口以加载数据,减少了 I/O 操作时的拷贝开销。

Selectivity 下推

数据自身的删除和更新也会导致读过程中需要根据 DeleteVector 过滤掉不可见的数据。此外在延迟物化中,需要将部分列数据先行加载进行计算,然后根据计算命中行读取其他列数据。Relyt 在这些场景读数据时,会将数据的 Selectivity 下推到 TableScan,根据 Selectivity 信息裁剪 Block,并根据命中率等信息决定是否在 Block 内将 Selectivity 转换为命中行集走 Page 裁剪链路。在同一个 Page 内,Selectivity 还可直接应用于数据解码链路,在解码时直接跳过相关数据,减少数据解码开销。

数据编解码

提升读数据性能的下一步是优化数据编解码和压缩,Relyt 在这方面也做了大量优化工作。下面主要从数据解码、字典读优化、自适应编码三个方面展开。

解码优化

Relyt采用 SIMD 指令减少解码和转换开销,同时 Relyt 在解码链路上采用了更精确的 BufferSize 估算方法,减少数据解码链路上 Buffer 反复扩缩带来的拷贝开销;部分链路热点采用减少分支判断、循环手动展开等方式,进一步优化数据解码性能。

字典读优化

字典编码是一种常见的数据编码方式,合理地使用字典编码可以有效降低存储空间,提高查询效率。Relyt 在读数据时,会根据数据类型及字典编码相关信息,动态决定是否将某列直接以字典编码的形式加载到内存。

业界通常做法:若某一列采用字典编码且读时也需按字典方式出数据,此时数据解码过程中会重新构建内存字典。由于字典编码是 ColumnChunk 级别,对于开启字典编码的列,写入过程中若发现数据不适合使用字典编码,则会将已经写入的数据按字典编码刷盘,后续数据使用明文写入,这会导致一个 Block 中同一列数据前部分 Page 按字典编码存储、后部分 Page 按明文存储,因此在读数据时需对未编码的 Page 重新进行字典编码,显而易见这种逆操作会极大降低性能。

Relyt 针对以上场景进行了优化,在读数据时,会同时考虑字典编码 Page 和非字典编码 Page,综合评估读的代价,决策是否以字典方式 or 非字典方式读;其次在读数据过程中,会根据收集到的统计信息直接读,尽量避免重新构建字典的开销。

自适应编码

选择合理的数据编码和压缩方式,需要综合考虑存储成本和查询性能,Relyt 通过自适应编码实现了用户透明。在新建表时,用户如果不指定列的数据编码方式,Relyt 会默认开启自适应编码。开启后,会针对表中每一列结合其数据类型,选择一种默认的编码和压缩方式,并在写入的过程中实时反馈,动态调整列的编码和压缩,实现局部数据最优。此外为减少局部数据的干扰,自适应编码和压缩结合了 AutoTableService 能力,实现全局视角的编码和压缩调优,使得落盘的数据文件在 Compaction 的过程中逐步使用最优的编码和压缩,降低存储成本和提升查询性能。

图片

以字典编码为例,未开启自适应编码时,同一个 ColumnChunk 中可能部分 Page 采用字典编码,部分 Page 采用明文存储;开启自适应编码后,同一个 ColumnChunk 中所有的 Page 都采用同一种编码方式;在经过 AutoTableService 对文件进行整理后,同一列的不同 ColumnChunk 的编码方式会尽可能一致,且开启自适应编码后,保证了写入数据的压缩比。

结语

为提升查询性能和存储性价比,Relyt AI-ready Data Cloud​​​​​​​在数据裁剪、编解码及压缩上进行了大量的优化工作,为客户带来了实实在在的优质体验。未来 Relyt 将会在这方面持续发力,为客户提供极致的查询性价比和更好的用户体验。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值