Parquet 格式的可重复性/确定性如何?
Posted
技术标签:
【中文标题】Parquet 格式的可重复性/确定性如何?【英文标题】:How reproducible / deterministic is Parquet format? 【发布时间】:2022-01-10 05:09:15 【问题描述】:我正在向非常熟悉 Apache Parquet 二进制布局的人寻求建议:
进行F(a) = b
的数据转换,其中F
是完全确定的,并且使用了整个软件堆栈(框架、箭头和parquet 库)的完全相同的版本 - 我获得相同二进制文件的可能性有多大每次将 b
保存到 Parquet 时,数据帧 b
在不同主机上的表示?
换句话说再现性如何 Parquet 是二进制级别的?当数据逻辑相同时,什么会导致二进制差异?
由于对齐,值之间是否存在一些 uninit 内存? 假设所有序列化设置(压缩、分块、使用字典等)都相同,结果是否仍会出现偏差?上下文
我正在开发一个系统,用于完全可重现和确定性的数据处理和计算数据集哈希以断言这些保证。
我的主要目标一直是确保数据集b
包含一个相同的记录集作为数据集b'
- 这当然与散列一个非常不同Arrow/Parquet 的二进制表示。不想处理存储格式的可重复性,我一直在内存中计算 逻辑数据哈希。这是缓慢但灵活的,例如即使记录被重新排序(我认为这是一个等效的数据集),我的哈希值也保持不变。
但是,当考虑与 IPFS
和其他依赖 文件哈希 的 content-addressable 存储集成时 - 只需一个即可大大简化设计哈希(物理)而不是两个(逻辑 + 物理),但这意味着我必须保证 Parquet 文件是可重现的。
更新
我决定暂时继续使用逻辑散列。
我创建了一个新的 Rust crate arrow-digest,它实现了 Arrow 数组和记录批次的稳定散列,并努力隐藏与编码相关的差异。 crate 的 README 描述了散列算法,如果有人发现它有用并希望用另一种语言实现它。
我将继续扩展支持的类型集,因为我正在将其集成到去中心化数据处理tool我正在研究中。
从长远来看,我不确定逻辑散列是最好的方法 - Parquet 的一个子集为了使文件布局具有确定性而牺牲了一些效率,这可能是内容寻址能力的更好选择。
【问题讨论】:
我对 Parquet 的了解还不够,无法回答这个问题。我的直觉说它不是确定性的,你可能会使用未初始化的填充。但是,我想指出,有许多不同的方法可以将相同的数据存储到 parquet 文件中。编写者可以选择写统计或不写统计,使用不同大小的行组或数据页大小,使用不同的编码方案和不同的压缩方案。所有这些都会为相同的数据生成不同的 parquet 文件。 谢谢!填充是我最关心的问题。统计数据和其他设置在我的控制之下,所以如果需要,我愿意禁用所有附加功能,只要我可以继续使用 Parquet 格式(由于它的广泛支持)。 【参考方案1】:至少在我期望的箭头实现中,但没有以相同的顺序验证完全相同的输入(包括相同的元数据)以产生确定性的输出(出于安全原因,我们尽量不留下未初始化的值)具有相同的配置(假设选择的压缩算法也做出了确定性保证)。元数据或其他地方可能存在一些哈希映射迭代,这也可能打破这一假设。
正如@Pace 指出的那样,我不会依赖它并建议不要依赖它)。规范中没有任何内容可以保证这一点,并且由于写入文件时会保留写入器版本,因此如果您决定升级,则可以保证损坏。如果添加或删除额外的元数据,事情也会中断(我相信过去已经对往返数据集进行了一些重大修复,这些问题会导致不确定性)。
所以总而言之,这可能会或可能不会在今天起作用,但即使它起作用,我预计这会非常脆弱。
【讨论】:
以上是关于Parquet 格式的可重复性/确定性如何?的主要内容,如果未能解决你的问题,请参考以下文章
由于某些字段的值未知,使用 Spark 写入 parquet 文件的数字格式异常 [重复]
使用dask有效地从blob存储上的parquet文件中读取一些列[重复]