在 Hugging Face Hub 上改进 Parquet 去重

Parquet 去重的挑战

为了降低存储成本,Hugging Face 使用字节级内容定义分块(Content-Defined Chunking,CDC)来进行数据去重。虽然 CDC 在许多文件类型的插入和删除操作中都很有效,但 Parquet 文件的特定布局在增量更新时会给高效去重带来挑战。

数据操作对去重的影响

Hugging Face 使用来自 FineWeb 数据集的 2GB、包含 1,092,000 行的 Parquet 文件进行实验,以分析不同操作对去重率的影响:

数据追加

追加 10,000 行新数据可实现高去重效率。由于追加仅影响文件末尾,新版本的去重率为 99.1%,仅需额外 20MB 存储。

数据修改

修改单行(例如第 10,000 行)会显著降低去重率。新文件的去重率仅为 89%,需要额外 230MB 存储。这是因为 Parquet 文件格式在列头中包含绝对文件偏移量(具体在 ColumnChunkColumnMetaData 结构中),导致任何修改都会导致所有列头被重新写入。

数据删除

从文件中部删除一行通常会导致剩余部分全部由新块组成,从而破坏文件后半段的去重。这主要是由于列压缩过于激进。关闭压缩虽能提升去重,但会使文件大小翻倍,形成存储效率与去重能力之间的权衡。

提出的解决方案:内容定义的行组

为在删除或插入时同时保持压缩和去重效率,Hugging Face 提出在行级而非仅字节级使用内容定义分块(Content-Defined Chunking)。

不再按固定行数(例如每 1,000 行)划分行组,而是依据提供的 “Key” 列的哈希值进行划分。当键列的哈希值对目标行数取模等于零时(并受最小、最大大小约束),即进行行组拆分。

实验结果表明,即使在删除行的情况下,该方法仍能在压缩的 Parquet 文件中实现高效去重,因为仅重写受影响的行组及列头。

Parquet 存储的未来优化

Hugging Face 确定了提升 Parquet 去重能力的两条主要路径:

  1. 相对偏移:将文件结构数据中的绝对偏移替换为相对偏移,使 Parquet 结构与位置无关。但这被认为是对文件格式的复杂改动。
  2. 内容定义的行组:在行组上实现内容定义分块的支持。由于 Parquet 格式并不要求行组大小统一,可通过更新 Parquet 写入器来实现,且对现有格式影响最小。

此外,Hugging Face 正在探索在上传前可选地重写 Parquet 文件以去除绝对文件偏移,并在下载时恢复的可能性。

Sources