Які відмінності між пером та паркетом?


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

Відповіді:


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

  • Паркет дорожче писати, ніж Feather, оскільки він має більше шарів кодування та стиснення. Перо - це немодифікована необроблена стовпчаста пам'ять стрілки. Можливо, ми додамо просте стиснення до Feather у майбутньому.

  • Через кодування словника, RLE-кодування та стиснення сторінки даних, паркетні файли часто будуть набагато меншими, ніж файли Feather

  • Паркет - це стандартний формат зберігання для аналітики, який підтримується багатьма різними системами: 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 я отримав дублікати двох із десяти прогонів. Просто згадуючи, якщо хтось використовує цю функцію, де унікальність повинна бути гарантована.
Дарконаут

1
@Darkonaut просто цікаво ... стиснення призводить до менших розмірів, тому було б швидше прочитати його в пам'ять. Можливо, додаткова обробка внаслідок стиснення / розпакування буде все одно швидшою, ніж необхідність читати більше байтів. Або у вас така ситуація, про яку я не думаю?
PascalVKooten

1
HDF5 є більш загальним і важким ... також більшу частину часу набагато повільніше.
ivo Welch,

3
@WesMcKinney Я помітив, що ваша відповідь була написана ще в 2018 році. Через 2,3 роки, як ви все ще вважаєте, що стрілка (перо) не підходить для тривалого зберігання (порівняно з паркетом)? Чи є конкретна причина? Як стабільність? еволюція формату? чи?
HCSF
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.