Snappy 是可拆分的还是不可拆分的?

Is Snappy splittable or not splittable?

根据这个Cloudera post,Snappy 是可拆分的。

For MapReduce, if you need your compressed data to be splittable, BZip2, LZO, and Snappy formats are splittable, but GZip is not. Splittability is not relevant to HBase data.

但是从 hadoop 权威指南来看,Snappy 是不可拆分的。

网上也有一些类似的信息。有人说它是可分割的,有人说它不是。

两者都正确,但级别不同。

根据 Cloudera 博客 http://blog.cloudera.com/blog/2011/09/snappy-and-hadoop/

One thing to note is that Snappy is intended to be used with a
container format, like Sequence Files or Avro Data Files, rather than being used directly on plain text, for example, since the latter is not splittable and can’t be processed in parallel using MapReduce. This is different to LZO, where is is possible to index LZO compressed files to determine split points so that LZO files can be processed efficiently in subsequent processing.

这意味着如果使用 Snappy 压缩整个文本文件,则文件 不可拆分 。但是如果文件中的每条记录都用 Snappy 压缩,那么文件 可以拆分 ,例如在带有块压缩的序列文件中。

说得更清楚一点,是不一样的:

<START-FILE>
  <START-SNAPPY-BLOCK>
     FULL CONTENT
  <END-SNAPPY-BLOCK>
<END-FILE>

<START-FILE>
  <START-SNAPPY-BLOCK1>
     RECORD1
  <END-SNAPPY-BLOCK1>
  <START-SNAPPY-BLOCK2>
     RECORD2
  <END-SNAPPY-BLOCK2>
  <START-SNAPPY-BLOCK3>
     RECORD3
  <END-SNAPPY-BLOCK3>
<END-FILE>

Snappy 块不可拆分,但带有 snappy 块的文件是可拆分的

hadoop 中的所有可拆分编解码器都必须实现 org.apache.hadoop.io.compress.SplittableCompressionCodec。查看 2.7 的 hadoop 源代码,我们看到 org.apache.hadoop.io.compress.SnappyCodec 没有实现这个接口,所以我们知道它是不可拆分的。

我刚刚在 HDFS 上使用 Spark 1.6.2 测试了相同数量的 workers/processor,在一个简单的 JSON 文件和由 snappy 压缩的文件之间:

  • JSON: 4 个文件,每个文件 12GB,Spark 创建 388 个任务(1 个任务按 HDFS 块)(4*12GB/128MB => 384)
  • Snappy:4 个文件,每个 3GB,Spark 创建 4 个任务

Snappy 文件是这样创建的:.saveAsTextFile("/user/qwant/benchmark_file_format/json_snappy", classOf[org.apache.hadoop.io.compress.SnappyCodec])

所以 Snappy 在 JSON.

中不能与 Spark 拆分

,如果您使用 parquet(或 ORC)文件格式代替 JSON,这将是可分割的(即使使用 gzip)。

Snappy 实际上不像 bzip 那样可拆分,但是当与 parquet 或 Avro 等文件格式一起使用时,不是压缩整个文件,而是使用 snappy 压缩文件格式中的块。

要了解使用 snappy 压缩方式压缩 parquet 文件时发生的情况,请查看 parquet 文件的结构 [来源 link]

在 parquet 文件中,记录被分成 row-groups [基本上是原始文件行的子集],每个 row-groups 由 data-pages [列块组成图像],每个列块由许多页面组成,其中实际记录以带有元数据的编码格式[列]存储。当您启用 snappy 压缩时,它会压缩整个页面!不是整个文件。基本上你得到了一个带有快速压缩的可拆分镶木地板。

snappy 的优点是它是一种非常轻量级的压缩编解码器。

注意:row-groups 和列块有默认大小限制,分别为 128MB 和 1MB [您可以更改这些默认设置],您可以将不同的压缩编解码器与镶木地板一起使用,例如gzip