Spark SQL - разница между форматами сжатия gzip, snappy и lzo

Я пытаюсь использовать Spark SQL для записи файла parquet.

По умолчанию Spark SQL поддерживает gzip, но также поддерживает и другие форматы сжатия, такие как snappy и lzo.

В чем разница между этими форматами сжатия?


person Shankar    schedule 04.03.2016    source источник
comment
Кажется, что по умолчанию Spark использует snappy, а не gzip. По крайней мере, это то, что я вижу на s3: файлы, созданные со строкой snappy как частью их имени.   -  person bashan    schedule 18.02.2017
comment
@bashan: последние версии spark изменили формат по умолчанию на snappy, до версии 1.6.1 я вижу, что формат сжатия паркета по умолчанию — gzip.   -  person Shankar    schedule 18.02.2017


Ответы (5)


Просто попробуйте их на своих данных.

lzo и snappy — это быстрые компрессоры и очень быстрые декомпрессоры, но с меньшим сжатием, по сравнению с gzip, который сжимает лучше, но немного медленнее.

person Mark Adler    schedule 04.03.2016

Коэффициент сжатия. Сжатие GZIP использует больше ресурсов ЦП, чем Snappy или LZO, но обеспечивает более высокий коэффициент сжатия.

Общее использование: GZip часто является хорошим выбором для холодных данных, к которым обращаются нечасто. Snappy или LZO лучше подходят для горячих данных, к которым часто обращаются.

Snappy часто работает лучше, чем LZO. Стоит запустить тесты, чтобы увидеть, обнаружите ли вы значительную разницу.

Разделение. Если вам нужно, чтобы сжатые данные можно было разделить, форматы BZip2, LZO и Snappy можно разделить, а GZip — нет.

GZIP сжимает данные на 30% больше по сравнению со Snappy и в 2 раза больше использует ЦП при чтении данных GZIP по сравнению с тем, который потребляет данные Snappy.

LZO фокусируется на скорости декомпрессии при низкой загрузке ЦП и более высоком сжатии за счет увеличения ЦП.

Для долгосрочного/статического хранения лучше использовать сжатие GZip.

Ознакомьтесь с кодом и результатами обширных исследований и тестов в этой статье (Производительность различных общих алгоритмы сжатия — некоторые из них невероятно быстрые!).

введите здесь описание изображения

person Ram Ghadiyaram    schedule 01.06.2019
comment
Я не могу предложить отредактировать ваш хороший пост, однако я хотел бы отметить, что bz2 действительно является разделяемым по умолчанию, но Snappy и LZO могут быть разделены с помощью Hadoop, потому что Hadoop, скорее всего, не будет разделяемым, если он сгенерирован другим инструментом, кроме предоставленного в библиотеке хауп. - person Kiwy; 23.06.2021

Используйте Snappy, если вы можете справиться с более высоким использованием диска для повышения производительности (более низкий процессор + Splittable).

Когда Spark по умолчанию переключился с GZIP на Snappy, это было причиной:

Согласно нашим тестам, распаковка gzip выполняется очень медленно (‹ 100 МБ/с), что ограничивает распаковку запросов. Snappy может распаковывать со скоростью ~ 500 МБ/с на одном ядре.

Быстро:

  • Место для хранения: высокое
  • Использование ЦП: Низкое
  • Возможность разделения: Да (1)

GZIP:

  • Место для хранения: средний
  • Загрузка процессора: средняя
  • Разделяемый: Нет

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

person Garren S    schedule 30.05.2017
comment
Это очень неправильно! Snappy нельзя разделить: блоки Snappy и GZip нельзя разделить: новый документ Cloudera: cloudera.com/documentation/enterprise/latest/topics/ - person Maziyar; 31.05.2019
comment
Далее в этой строке говорится, что блоки Snappy и GZip не являются разделяемыми, но файлы с блоками Snappy внутри формата файла-контейнера, такого как SequenceFile или Avro, могут быть разделены. Здесь речь идет о паркете. Snappy можно разделить при использовании в Parquet, как указано в ответе. - person Garren S; 01.06.2019
comment
Это имеет смысл, извините, я пропустил последнюю часть вопроса. Спасибо друг. - person Maziyar; 01.06.2019

Основываясь на приведенных ниже данных, я бы сказал, что gzip выигрывает за пределами таких сценариев, как потоковая передача, где важна задержка во время записи.

Важно помнить, что скорость — это, по сути, стоимость вычислений. Однако облачные вычисления — это разовые затраты, а облачное хранилище — постоянные затраты. Компромисс зависит от периода хранения данных.


Проверим скорость и размер больших и малых parquet файлов в Python.

Результаты (большой файл, 117 МБ):

        +----------+----------+--------------------------+
        | 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 КБ, набор данных Iris):

        +---------+---------+--------------------------+
        | 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

большой_файл.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
person HashRocketSyntax    schedule 24.09.2020

Я согласен с 1 ответом(@Mark Adler) и у меня есть некоторая исследовательская информация[1], но я не согласен со вторым ответом(@Garren S)[2]. Возможно, Гаррен неправильно понял вопрос, потому что: [2] Parquet можно разделить со всеми поддерживаемыми кодеками: Разделяется ли сжатый файл Parquet в HDFS для Spark?, Tom White's Hadoop: The Definitive Guide, 4-е издание, Глава 5: ввод-вывод Hadoop, стр. 106. [1] Мои исследования: источник данных - 205 ГБ. Текст (разделенные поля), несжатый. выходные данные:

<!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 на EMR, состоящем из 2 м4.16xlarge. Преобразование - выделить все поля с упорядочением по нескольким полям. Это исследование, конечно, не стандартное, но хоть немного показывает реальное сравнение. С другими наборами данных и результаты вычислений могут быть другими.

person sunKazakh    schedule 20.11.2018