如何在不缓冲的情况下使用parquet-cpp编写流/面向行的数据?

时间:2017-08-08 15:57:30

标签: c++ parquet

我基本上面向行/流数据(Netflow)进入我的C ++应用程序,我想将数据写入Parquet-gzip文件。

查看parquet-cpp项目中的sample reader-writer.cc program,似乎我只能以柱状方式将数据提供给parquet-cpp:

constexpr int NUM_ROWS_PER_ROW_GROUP = 500;
...
// Append a RowGroup with a specific number of rows.
parquet::RowGroupWriter* rg_writer = file_writer->AppendRowGroup(NUM_ROWS_PER_ROW_GROUP);

// Write the Bool column
for (int i = 0; i < NUM_ROWS_PER_ROW_GROUP; i++) {
   bool_writer->WriteBatch(1, nullptr, nullptr, &value);
}
// Write the Int32 column
...
// Write the ... column

这似乎意味着我需要自己缓冲NUM_ROWS_PER_ROW_GROUP行,然后循环遍历它们,一次将它们传输到parquet-cpp一列。我希望有一种更好的方法,因为这似乎效率低下,因为数据需要被复制两次:一次进入我的缓冲区,然后再次将数据一次性送入一个专栏中的一个专栏。

有没有办法将每行的数据放入parquet-cpp而不必先缓冲一堆行? Apache Arrow项目(parquet-cpp使用)具有a tutorial that shows how to convert row-wise data into an Arrow table。对于每行输入数据,代码将附加到每个列构建器:

for (const data_row& row : rows) {
   ARROW_RETURN_NOT_OK(id_builder.Append(row.id));
   ARROW_RETURN_NOT_OK(cost_builder.Append(row.cost));

我想用镶木地板做一些类似的事情。这可能吗?

1 个答案:

答案 0 :(得分:4)

由于我们需要从行方式转换为柱状表示,因此您将永远无法进行缓冲。在编写本文时,最好的路径是构建Apache Arrow表,然后将其输入parquet-cpp

parquet-cpp提供特殊的Arrow API,然后可以直接对这些表进行操作,大多数情况下不需要任何其他数据副本。您可以在parquet/arrow/reader.hparquet/arrow/writer.h中找到API。

最佳但尚未实现的解决方案可以通过执行以下操作来节省一些字节:

  • 在新的parquet-cpp API中逐行摄取
  • 使用指定的编码和压缩设置
  • 直接对每列的值进行编码
  • 仅在内存中缓冲此内容
  • 在行组的末尾,写出列
  • 之后的列

虽然这个最佳解决方案可能会为您节省一些内存,但仍有一些步骤需要由某人实施(随意提供或执行这些步骤请求帮助),您可能对基于Apache Arrow的方式很好API。