Parquet中固定长度列表的快速路径

Parquet中固定长度列表的快速路径

💡 原文英文,约2900词,阅读约需11分钟。
📝

内容提要

Apache Parquet存储固定长度列表(如向量嵌入)效率低,因Dremel编码开销大。Hardwood通过检测定义和重复级别流,识别固定长度列表并绕过常规解码,实现快速路径。列读取器提速达2.5倍,行读取器最高3.9倍,接近扁平列性能。该优化可选启用,预计1.1版默认开启。

🔎

延伸解读

为什么固定长度列表在Parquet中效率低

Parquet使用Dremel编码处理嵌套和重复数据,即使列表长度固定,也会为每个元素记录定义级别和重复级别。对于固定长度列表,重复级别流呈现周期性模式(如0,1,1,0,1,1...),这种冗余编码导致解码开销约为扁平列的三倍。社区正在讨论添加FIXED_SIZE_LIST逻辑类型,但尚未落地。

快速路径的检测原理

Hardwood通过扫描编码后的定义级别和重复级别流,检测数据页中的列表是否实际为固定长度。定义级别流若为全最大值,则O(1)判断无空值;重复级别流则通过模式匹配(如位打包的周期模式或RLE运行)识别固定长度。检测到后,绕过常规Dremel重建,直接按页复制值,避免生成级别数组,减少GC压力。

性能提升与适用场景

列读取器提速约2.5倍,行读取器最高3.9倍(列表长度64-256时),接近扁平列性能。短列表(如3元素)提升较小,长列表(如768维嵌入)提升显著。该优化对可变长度列表的检测开销极低(通常<0.1%),但列表长度为15时开销约2%。适用于存储向量嵌入、坐标等固定长度数据的场景。

启用方式与未来展望

该优化在Hardwood 1.1.0.Beta1中需显式启用,设置解析选项hardwood.fixed-list-fast-path为true,预计1.1正式版默认开启。一旦Parquet格式支持FIXED_SIZE_LIST,此优化对新写入文件不再必要,但对现有数据仍有价值。

Q&A

Parquet 存储固定长度列表(如向量嵌入)的主要问题是什么?

Parquet 使用 Dremel 编码来存储列表,即使列表长度固定,也会为每一行记录定义级别和重复级别,导致解码开销大,性能比扁平列存储慢约 3 倍。

Hardwood 如何实现固定长度列表的快速路径?

Hardwood 通过扫描编码的定义级别和重复级别流,检测数据页中的列表是否实际为固定长度。如果检测成功,则绕过常规的 Dremel 记录重建机制,直接按页复制值,避免逐元素处理和级别数组的物化。

Hardwood 的固定长度列表快速路径能带来多大的性能提升?

性能提升取决于列表长度和读取器类型。列读取器通常提速约 2.5 倍,行读取器在列表长度中等(约 64-256)时最高可达 3.9 倍,对于长列表(如 768 元素)也能达到接近扁平列的性能。

Hardwood 的固定长度列表快速路径如何检测重复级别流中的固定长度模式?

检测重复级别流时,根据列表长度 n 分为三种情况:n≤8 时使用位打包模式匹配;n≥16 时利用字节周期性和批量比较;9≤n≤15 时使用标量回退方法逐记录检查。检测器不硬编码特定模式,而是从第一条记录推导出步长并验证整个流是否重复该模式。

Hardwood 的固定长度列表快速路径目前如何启用?

该优化目前是可选启用的,需要设置解析器选项 hardwood.fixed-list-fast-path 为 true。预计在 1.1 版本中默认启用。

Hardwood 的固定长度列表快速路径对常规可变长度列表有性能影响吗?

检测逻辑本身有开销,但通常很小。对于 n≤8 的情况,检测开销约为常规列表检索成本的 1.7%;对于较大的 n,开销低于 0.1%。即使在最坏情况下(如 n=15),端到端解析时间的影响也仅为约 2%,通常可以忽略。

Parquet 社区计划如何从格式层面解决固定长度列表的存储效率问题?

Parquet 社区正在讨论添加新的逻辑类型 FIXED_SIZE_LIST,以原生支持固定长度列表,从而避免 Dremel 编码的开销,使解码性能达到扁平模式的水平。

🏷️

标签

➡️

继续阅读