我正在寻求对Apache Parquet二进制布局非常熟悉的人的建议:
在使用完全确定性的数据转换F(a) = b,以及相同版本的整个软件堆栈(框架、箭头和Parquet库)的情况下,每次将b保存到Parquet时,在不同的主机上获得dataframe b的相同二进制表示的可能性有多大?
换句话说,Parquet在二进制级别上有多可重复?当数据在逻辑上相同时,什么因素会导致二进制差异?
- 由于对齐而导致值之间存在未初始化的内存吗? - 假设所有序列化设置(压缩、分块、使用字典等)都相同,结果是否仍会漂移?
背景:
我正在开发一个系统,用于完全可重现和确定性数据处理,并计算数据集哈希以断言这些保证。
我的主要目标是确保数据集b与数据集b'包含完全相同的记录,这当然与对Arrow/Parquet的二进制表示进行哈希处理非常不同。我不想处理存储格式的可重复性,因此我一直在内存中计算逻辑数据哈希。这很慢但很灵活,例如,即使记录被重新排序(我认为这是等效的数据集),我的哈希值仍然相同。
但是,当考虑与
在使用完全确定性的数据转换F(a) = b,以及相同版本的整个软件堆栈(框架、箭头和Parquet库)的情况下,每次将b保存到Parquet时,在不同的主机上获得dataframe b的相同二进制表示的可能性有多大?
换句话说,Parquet在二进制级别上有多可重复?当数据在逻辑上相同时,什么因素会导致二进制差异?
- 由于对齐而导致值之间存在未初始化的内存吗? - 假设所有序列化设置(压缩、分块、使用字典等)都相同,结果是否仍会漂移?
背景:
我正在开发一个系统,用于完全可重现和确定性数据处理,并计算数据集哈希以断言这些保证。
我的主要目标是确保数据集b与数据集b'包含完全相同的记录,这当然与对Arrow/Parquet的二进制表示进行哈希处理非常不同。我不想处理存储格式的可重复性,因此我一直在内存中计算逻辑数据哈希。这很慢但很灵活,例如,即使记录被重新排序(我认为这是等效的数据集),我的哈希值仍然相同。
但是,当考虑与
IPFS
和其他基于内容寻址的存储集成时,这些存储依赖于文件的哈希值,只有一个哈希值(物理)而不是两个(逻辑+物理)会大大简化设计,但这意味着我必须保证Parquet文件是可重现的。
更新
我决定继续使用逻辑哈希。
我创建了一个新的Rust crate arrow-digest,实现了Arrow数组和记录批处理的稳定哈希,并努力隐藏编码相关的差异。如果有人发现它有用并想在另一种语言中实现它,该crate的README描述了哈希算法。
随着我将其集成到我正在开发的分散式数据处理工具中,我将继续扩展支持的类型集。
从长远来看,我不确定逻辑哈希是否是前进的最佳方式 - Parquet的子集可能更好,它做出了一些效率上的牺牲,只是为了使文件布局确定性。