В чем разница между пером и паркетом?

89

Оба являются колоночными (дисковыми) форматами хранения для использования в системах анализа данных. Оба интегрированы в Apache Arrow ( пакет pyarrow для python) и предназначены для соответствия со Arrow как столбцовым аналитическим слоем в памяти.

Чем отличаются оба формата?

Всегда ли вы предпочитаете перо при работе с пандами, когда это возможно?

В каких случаях перо подходит больше, чем паркет, и наоборот?


Приложение

Я нашел здесь несколько подсказок https://github.com/wesm/feather/issues/188 , но, учитывая молодой возраст этого проекта, он, возможно, немного устарел.

Несерьезный тест скорости, потому что я просто выгружаю и загружаю весь Dataframe, но чтобы дать вам некоторое впечатление, если вы никогда раньше не слышали о форматах:

 # IPython    
import numpy as np
import pandas as pd
import pyarrow as pa
import pyarrow.feather as feather
import pyarrow.parquet as pq
import fastparquet as fp


df = pd.DataFrame({'one': [-1, np.nan, 2.5],
                   'two': ['foo', 'bar', 'baz'],
                   'three': [True, False, True]})

print("pandas df to disk ####################################################")
print('example_feather:')
%timeit feather.write_feather(df, 'example_feather')
# 2.62 ms ± 35.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
print('example_parquet:')
%timeit pq.write_table(pa.Table.from_pandas(df), 'example.parquet')
# 3.19 ms ± 51 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
print()

print("for comparison:")
print('example_pickle:')
%timeit df.to_pickle('example_pickle')
# 2.75 ms ± 18.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
print('example_fp_parquet:')
%timeit fp.write('example_fp_parquet', df)
# 7.06 ms ± 205 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)
print('example_hdf:')
%timeit df.to_hdf('example_hdf', 'key_to_store', mode='w', table=True)
# 24.6 ms ± 4.45 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)
print()

print("pandas df from disk ##################################################")
print('example_feather:')
%timeit feather.read_feather('example_feather')
# 969 µs ± 1.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
print('example_parquet:')
%timeit pq.read_table('example.parquet').to_pandas()
# 1.9 ms ± 5.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

print("for comparison:")
print('example_pickle:')
%timeit pd.read_pickle('example_pickle')
# 1.07 ms ± 6.21 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
print('example_fp_parquet:')
%timeit fp.ParquetFile('example_fp_parquet').to_pandas()
# 4.53 ms ± 260 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)
print('example_hdf:')
%timeit pd.read_hdf('example_hdf')
# 10 ms ± 43.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

# pandas version: 0.22.0
# fastparquet version: 0.1.3
# numpy version: 1.13.3
# pandas version: 0.22.0
# pyarrow version: 0.8.0
# sys.version: 3.6.3
# example Dataframe taken from https://arrow.apache.org/docs/python/parquet.html
Darkonaut
источник

Ответы:

131
  • Формат Parquet предназначен для длительного хранения, где Arrow больше предназначен для краткосрочного или временного хранения (Arrow может быть более подходящим для длительного хранения после выпуска 1.0.0, поскольку в этом случае двоичный формат будет стабильным)

  • Писать Parquet дороже, чем Feather, поскольку в нем больше уровней кодирования и сжатия. Перо - это неизмененная необработанная колоночная память со стрелками. Возможно, в будущем мы добавим простое сжатие в Feather.

  • Из-за кодирования словаря, кодирования RLE и сжатия страницы данных файлы Parquet часто бывают намного меньше файлов Feather.

  • Parquet - это стандартный формат хранения аналитики, поддерживаемый множеством различных систем: Spark, Hive, Impala, различными сервисами AWS, в будущем BigQuery и т. Д. Поэтому, если вы занимаетесь аналитикой, Parquet - хороший вариант в качестве эталонного формата хранения для запрос из нескольких систем

Показанные вами тесты будут очень шумными, поскольку данные, которые вы читаете и пишете, очень малы. Вы должны попробовать сжать не менее 100 МБ или более 1 ГБ данных, чтобы получить более информативные тесты, см., Например, http://wesmckinney.com/blog/python-parquet-multithreading/

Надеюсь это поможет

Уэс МакКинни
источник
2
Да, вариант «без сжатия» всегда будет
Уэс МакКинни
1
Я заметил, что ваша generate_floatsфункция в вашем тестовом коде здесь wesmckinney.com/blog/python-parquet-update не гарантирует unique_values. Они просто случайны. При n = 100M я получил дубликаты в двух из десяти прогонов. Просто упомяну на случай, если кто-то использует эту функцию, когда уникальность должна быть гарантирована.
Darkonaut 07
1
@Darkonaut просто интересно ... сжатие приводит к меньшему размеру, поэтому его будет быстрее прочитать в памяти. Может случиться так, что дополнительная обработка из-за сжатия / распаковки будет все же быстрее, чем необходимость чтения большего количества байтов. Или у вас есть ситуация, о которой я не думаю?
PascalVKooten
1
HDF5 более общий и тяжелый ... также большую часть времени намного медленнее.
ivo Welch
3
@WesMcKinney Я заметил, что ваш ответ был написан еще в 2018 году. По прошествии 2,3 лет вы все еще думаете, что Arrow (перо) не подходит для длительного хранения (по сравнению с Parquet)? Есть конкретная причина? Нравится стабильность? эволюция формата? или?
HCSF