Spark SQL - gzip vs snappy vs lzo 压缩格式之间的区别

Posted

技术标签:

【中文标题】Spark SQL - gzip vs snappy vs lzo 压缩格式之间的区别【英文标题】:Spark SQL - difference between gzip vs snappy vs lzo compression formats 【发布时间】:2016-06-17 19:06:49 【问题描述】:

我正在尝试使用 Spark SQL 编写 parquet 文件。

默认情况下,Spark SQL 支持gzip,但它也支持其他压缩格式,例如snappylzo

这些压缩格式有什么区别?

【问题讨论】:

看来 Spark 默认使用“snappy”而不是“gzip”。至少这是我在 s3 上看到的:使用字符串“snappy”创建的文件作为其名称的一部分。 @bashan:最近版本的 spark 将默认格式更改为 snappy,直到 1.6.1 我可以看到默认 parquet 压缩格式是 gzip。 【参考方案1】:

压缩比: GZIP 压缩比 Snappy 或 LZO 使用更多的 CPU 资源,但提供更高的压缩比。

一般用法: 对于不经常访问的数据,GZip 通常是一个不错的选择。 对于经常访问的数据,Snappy 或 LZO 是更好的选择。

Snappy 通常比 LZO 表现更好。值得进行测试,看看您是否发现了显着差异。

可拆分性: 如果您需要压缩数据可拆分,BZip2、LZO 和 Snappy 格式是可拆分的,但 GZip 不是。

与使用 Snappy 数据相比,在读取 GZIP 数据时,GZIP 的数据压缩率比 Snappy 多 30%,而 CPU 比使用 Snappy 数据的多 2 倍。

LZO 专注于在低 CPU 使用率下的解压缩速度和以更多 CPU 为代价的更高压缩率。

对于长期/静态存储,GZip 压缩仍然更好。

See extensive research and benchmark code and results in this article (Performance of various general compression algorithms – some of them are unbelievably fast!).

【讨论】:

我不能提议对你的好帖子进行编辑,但是我想指出 bz2 确实是原生可拆分的,但 Snappy 和 LZO 可以被 hadoop 吐出,如果它们很可能不会被拆分由 hadoop 库中提供的工具以外的其他工具生成。【参考方案2】:

根据下面的数据,我认为gzip 在流式传输等场景之外胜出,其中写入时间延迟很重要。

请务必记住,速度本质上就是计算成本。但是,云计算是一次性成本,而云存储是经常性成本。权衡取舍取决于数据的保留期限。


让我们在 Python 中测试大小 parquet 文件的速度和大小。

结果(大文件,117 MB):

        +----------+----------+--------------------------+
        | snappy   | gzip     | (gzip-snappy)/snappy*100 |
+-------+----------+----------+--------------------------+
| write | 1.62 ms  | 7.65 ms  | 372% slower              |
+-------+----------+----------+--------------------------+
| size  | 35484122 | 17269656 |  51% smaller             |
+-------+----------+----------+--------------------------+
| read  | 973 ms   | 1140 ms  |  17% slower              |
+-------+----------+----------+--------------------------+

结果(小文件,4 KB,鸢尾花数据集):

        +---------+---------+--------------------------+
        | snappy  | gzip    | (gzip-snappy)/snappy*100 |
+-------+---------+---------+--------------------------+
| write | 1.56 ms | 2.09 ms | 33.9% slower             |
+-------+---------+---------+--------------------------+
| size  | 6990    | 6647    |  5.2% smaller            |
+-------+---------+---------+--------------------------+
| read  | 3.22 ms | 3.44 ms |  6.8% slower             |
+-------+---------+---------+--------------------------+

small_file.ipynb

import os, sys
import pyarrow
import pandas as pd
import numpy as np
from sklearn.datasets import load_iris

iris = load_iris()

df = pd.DataFrame(
    data= np.c_[iris['data'], iris['target']],
    columns= iris['feature_names'] + ['target']
)

# ========= WRITE =========
%timeit df.to_parquet(path='iris.parquet.snappy', compression='snappy', engine='pyarrow', index=True)
# 1.56 ms

%timeit df.to_parquet(path='iris.parquet.gzip', compression='snappy', engine='pyarrow', index=True)
# 2.09 ms

# ========= SIZE =========
os.stat('iris.parquet.snappy').st_size
# 6990

os.stat('iris.parquet.gzip').st_size
# 6647

# ========= READ =========
%timeit pd.read_parquet(path='iris.parquet.snappy', engine='pyarrow')
# 3.22 ms

%timeit pd.read_parquet(path='iris.parquet.gzip', engine='pyarrow')
# 3.44 ms

large_file.ipynb

import os, sys
import pyarrow
import pandas as pd

df = pd.read_csv('file.csv')

# ========= WRITE =========
%timeit df.to_parquet(path='file.parquet.snappy', compression='snappy', engine='pyarrow', index=True)
# 1.62 s

%timeit df.to_parquet(path='file.parquet.gzip', compression='gzip', engine='pyarrow', index=True)
# 7.65 s

# ========= SIZE =========
os.stat('file.parquet.snappy').st_size
# 35484122

os.stat('file.parquet.gzip').st_size
# 17269656

# ========= READ =========
%timeit pd.read_parquet(path='file.parquet.snappy', engine='pyarrow')
# 973 ms

%timeit pd.read_parquet(path='file.parquet.gzip', engine='pyarrow')
# 1.14 s

【讨论】:

【参考方案3】:

我同意 1 个答案(@Mark Adler)并有一些研究信息[1],但我不同意第二个答案(@Garren S)[2]。也许加伦误解了这个问题,因为: [2] Parquet splitable with all supported codecs:Is gzipped Parquet file splittable in HDFS for Spark?,Tom White 的 Hadoop:权威指南,第 4 版,第 5 章:Hadoop I/O,第 106 页。 [1] 我的研究: 源数据 - 205 GB。文本(分隔字段),未压缩。 输出数据:

<!DOCTYPE html>
<html>

<head>
  <style>
    table,
    th,
    td 
      border: 1px solid black;
      border-collapse: collapse;
    
  </style>
</head>

<body>

  <table style="width:100%">
    <tr>
      <th></th>
      <th>time of computing, hours</th>
      <th>volume, GB</th>
    </tr>
    <tr>
      <td>ORC with default codec</td>
      <td>3-3,5</td>
      <td>12.3</td>
    </tr>
    <tr>
      <td>Parquet with GZIP</td>
      <td>3,5-3,7</td>
      <td>12.9</td>
    </tr>
    <tr>
      <td>Parquet with SNAPPY</td>
      <td>2,5-3,0</td>
      <td>60.4</td>
    </tr>
  </table>

</body>

</html>

使用 Hive 在由 2 m4.16xlarge 组成的 EMR 上执行转换。 转换 - 选择按多个字段排序的所有字段。 这项研究当然不是标准的,但至少有一点显示了真正的比较。与其他数据集和计算结果可能会有所不同。

【讨论】:

【参考方案4】:

如果您可以处理更高的磁盘使用率以获得性能优势(更低的 CPU + 可拆分),请使用 Snappy。

当 Spark 默认从 GZIP 切换到 Snappy 时,原因如下:

根据我们的测试,gzip 解压非常慢(

活泼的:

存储空间:高 CPU 使用率:低 可拆分: (1)

GZIP:

存储空间:中等 CPU 使用率:中等 可拆分:

1) http://boristyukin.com/is-snappy-compressed-parquet-file-splittable/

【讨论】:

该行继续说“Snappy 和 GZip 块不可拆分,但容器文件格式(如 SequenceFile 或 Avro)内具有 Snappy 块的文件可以拆分。”我们在这里谈论镶木地板。 Snappy 在 Parquet 中使用时是可拆分的,如答案中所述。 有道理,抱歉我错过了问题的最后一部分。谢谢老兄。 据此***.com/questions/43323882/… parquet 文件可以独立于使用的压缩进行拆分,因此我不确定比较中的第三点是否成立。【参考方案5】:

只需在您的数据上尝试一下。

lzo 和 snappy 是快速压缩器和非常快速的解压缩器,但压缩比 gzip 压缩得更好,但速度稍慢。

【讨论】:

以上是关于Spark SQL - gzip vs snappy vs lzo 压缩格式之间的区别的主要内容,如果未能解决你的问题,请参考以下文章

Hive with Hadoop vs Hive with spark vs spark sql vs HDFS - 它们如何相互协作?

不使用 first() 的 Spark SQL vs Normal SQL 查询错误

Spark 支持 gzip 格式吗?

Spark数据集何时使用Except vs Left Anti Join

在 Spark 2.0 中加载压缩的 gzipped csv 文件

Spark 仓库 VS Hive 仓库