我正在从流中读取Avro消息,并使用parquet.hadoop.ParquetWriter将它们写到Parquet文件中。我正在尝试使输出文件的大小超过阈值限制。问题是ParquetWriter将所有内容保留在内存中,并且仅在关闭writer时才将其写到磁盘上。根据Parquet文档,数据以最终格式写入内存对象,这意味着内存中对象的大小与磁盘上的最终大小相同。我的问题是如何确定内存中写入数据的大小,以便决定关闭写入器?
我尝试使用写入ParquetWriter的avro消息的字节大小作为Parquet编写器文件大小的估计值,但由于Parquet存储数据的方式(列格式)不同,因此与Parquet编写器大小有很大差异。这是我所做的伪代码:
ParquetWriter parquetWriter = new ParquetWriter(..., BLOCK_SIZE, PAGE_SIZE);
long bytesWrittenSofar = 0;
public long getLength(){
return bytesWrittenSofar;
}
public void write(org.apache.avro.generic.GenericRecord record){
parquetWriter.write(record);
bytesWrittenSofar += avroToBytes(record).length;
}
public static byte[] avroToBytes(GenericRecord record){
GenericDatumWriter<GenericRecord> writer =
new GenericDatumWriter<GenericRecord>(record.getSchema());
ByteArrayOutputStream out = new ByteArrayOutputStream();
BinaryEncoder encoder = EncoderFactory.get().binaryEncoder(out, null);
writer.write(record, encoder);
encoder.flush();
out.close();
return out.toByteArray();
}
事实证明,我从getLength()获得的值与实木复合地板文件的实际文件大小有很大不同。我知道该架构将添加到文件的末尾,但这很小。只是给您一个想法,当getLength()报告为130MB时,实际文件大小仅为80MB。