Quelles sont les différences entre la plume et le parquet?

89

Les deux sont des formats de stockage (sur disque) en colonnes à utiliser dans les systèmes d'analyse de données. Les deux sont intégrés dans Apache Arrow ( package pyarrow pour python) et sont conçus pour correspondre à Arrow en tant que couche d'analyse en mémoire en colonne.

En quoi les deux formats diffèrent-ils?

Devriez-vous toujours préférer la plume lorsque vous travaillez avec des pandas lorsque cela est possible?

Quels sont les cas d'utilisation où la plume est plus adaptée que le parquet et inversement ?


annexe

J'ai trouvé quelques indices ici https://github.com/wesm/feather/issues/188 , mais étant donné le jeune âge de ce projet, il est peut-être un peu dépassé.

Ce n'est pas un test de vitesse sérieux car je ne fais que vider et charger un Dataframe entier, mais pour vous donner une impression si vous n'avez jamais entendu parler des formats auparavant:

 # 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
la source

Réponses:

131
  • Le format Parquet est conçu pour le stockage à long terme, où Arrow est plus destiné au stockage à court terme ou éphémère (Arrow peut être plus adapté au stockage à long terme après la sortie de la version 1.0.0, car le format binaire sera alors stable)

  • Parquet est plus cher à écrire que Feather car il comporte plus de couches d'encodage et de compression. Feather est une mémoire de flèche en colonne brute non modifiée. Nous ajouterons probablement une simple compression à Feather à l'avenir.

  • En raison de l'encodage du dictionnaire, du codage RLE et de la compression des pages de données, les fichiers Parquet seront souvent beaucoup plus petits que les fichiers Feather

  • Parquet est un format de stockage standard pour l'analyse pris en charge par de nombreux systèmes différents: Spark, Hive, Impala, divers services AWS, à l'avenir par BigQuery, etc. Donc, si vous effectuez des analyses, Parquet est une bonne option en tant que format de stockage de référence pour requête par plusieurs systèmes

Les benchmarks que vous avez montrés vont être très bruyants car les données que vous lisez et écrivez sont très petites. Vous devriez essayer de compresser au moins 100 Mo ou plus de 1 Go de données pour obtenir des benchmarks plus informatifs, voir par exemple http://wesmckinney.com/blog/python-parquet-multithreading/

J'espère que cela t'aides

Wes McKinney
la source
2
Oui, "non compressé" sera toujours une option
Wes McKinney
1
J'ai remarqué que votre generate_floatsfonction dans votre code de référence ici wesmckinney.com/blog/python-parquet-update ne garantit pas unique_values. Ils sont simplement aléatoires. Avec n = 100M, j'ai eu des doublons deux fois sur dix. Il suffit de mentionner au cas où quelqu'un utiliserait cette fonction où l'unicité devrait être garantie.
Darkonaut
1
@Darkonaut se demande simplement ... la compression entraîne une taille plus petite, il serait donc plus rapide de la lire en mémoire. Il se peut que le traitement supplémentaire dû à la compression / décompression soit encore plus rapide que d'avoir à lire plus d'octets. Ou avez-vous une situation à laquelle je ne pense pas?
PascalVKooten
1
HDF5 est plus général et lourd ... aussi beaucoup plus lent la plupart du temps.
ivo Welch
3
@WesMcKinney J'ai remarqué que votre réponse avait été écrite en 2018. Après 2,3 ans, pensez-vous toujours que Arrow (plume) n'est pas bon pour le stockage à long terme (par rapport au Parquet)? Y a-t-il une raison spécifique? Vous aimez la stabilité? évolution du format? ou?
HCSF