Maison > Java > javaDidacticiel > Algorithmes de compression dans Parquet Java

Algorithmes de compression dans Parquet Java

Mary-Kate Olsen
Libérer: 2025-01-20 18:04:12
original
980 Les gens l'ont consulté

Compression algorithms in Parquet Java

Apache Parquet est un format de stockage en colonnes destiné aux charges de travail analytiques, mais il peut être utilisé pour stocker tout type de données structurées, répondant à une variété de cas d'utilisation.

L'une de ses fonctionnalités les plus remarquables est la capacité de compresser efficacement les données en utilisant différentes techniques de compression aux deux étapes du processus de traitement. Cela réduit les coûts de stockage et améliore les performances de lecture.

Cet article explique la compression de fichiers de Parquet en Java, fournit des exemples d'utilisation et analyse ses performances.

Technologie de compression

Contrairement aux formats de stockage traditionnels basés sur les lignes, Parquet utilise une approche en colonnes, permettant l'utilisation de techniques de compression plus spécifiques et efficaces basées sur la localité et la redondance des valeurs du même type de données.

Parquet écrit les informations au format binaire et applique une compression à deux niveaux différents, chacun utilisant une technique différente :

  • Lors de l'écriture de la valeur de la colonne, il sélectionnera de manière adaptative le type d'encodage en fonction des caractéristiques de la valeur initiale : encodage par dictionnaire, encodage en longueur, compression de bits, encodage incrémental, etc.
  • Chaque fois qu'un certain nombre d'octets est atteint (la valeur par défaut est 1 Mo), une page est formée et le bloc binaire est compressé à l'aide d'un algorithme configurable par le programmeur (pas de compression, GZip, Snappy, LZ4, ZSTD, etc.).

Bien que l'algorithme de compression soit configuré au niveau du fichier, l'encodage de chaque colonne est automatiquement sélectionné à l'aide d'une heuristique interne (au moins dans l'implémentation parquet-java).

Les performances des différentes technologies de compression dépendent fortement de vos données. Il n'existe donc pas de solution universelle garantissant le temps de traitement le plus rapide et la consommation de stockage la plus faible. Vous devez effectuer vos propres tests.

Code

La configuration est simple et ne nécessite qu'un paramétrage explicite lors de l'écriture. Lors de la lecture d'un fichier, Parquet découvre quel algorithme de compression est utilisé et applique l'algorithme de décompression correspondant.

Configurer l'algorithme ou le codec

Dans Carpet and Parquet utilisant Protocol Buffers et Avro, pour configurer l'algorithme de compression, il suffit d'appeler la méthode withCompressionCodec du constructeur :

Tapis

<code class="language-java">CarpetWriter<T> writer = new CarpetWriter.Builder<>(outputFile, clazz)
    .withCompressionCodec(CompressionCodecName.ZSTD)
    .build();</code>
Copier après la connexion
Copier après la connexion
Copier après la connexion

Avro

<code class="language-java">ParquetWriter<Organization> writer = AvroParquetWriter.<Organization>builder(outputFile)
    .withSchema(new Organization().getSchema())
    .withCompressionCodec(CompressionCodecName.ZSTD)
    .build();</code>
Copier après la connexion
Copier après la connexion

Tampons de protocole

<code class="language-java">ParquetWriter<Organization> writer = ProtoParquetWriter.<Organization>builder(outputFile)
    .withMessage(Organization.class)
    .withCompressionCodec(CompressionCodecName.ZSTD)
    .build();</code>
Copier après la connexion
Copier après la connexion

La valeur doit être l'une des valeurs disponibles dans l'énumération CompressionCodecName : UNCOMPRESSED, SNAPPY, GZIP, LZO, BROTLI, LZ4, ZSTD et LZ4_RAW (LZ4 est obsolète, LZ4_RAW doit être utilisé).

Niveau de compression

Certains algorithmes de compression permettent d'affiner le niveau de compression. Ce niveau est généralement lié à l'effort qu'ils doivent déployer pour trouver des modèles répétitifs ; plus le niveau de compression est élevé, plus le processus de compression nécessite du temps et de la mémoire.

Bien qu'ils soient livrés avec des valeurs par défaut, ils peuvent être modifiés à l'aide du mécanisme de configuration générique de Parquet, bien qu'en utilisant des clés différentes pour chaque codec.

De plus, les valeurs à choisir ne sont pas standards et dépendent de chaque codec, vous devez donc vous référer à la documentation de chaque algorithme pour comprendre ce que propose chaque niveau.

ZSTD

Pour référencer la configuration au niveau, le codec ZSTD déclare une constante : ZstandardCodec.PARQUET_COMPRESS_ZSTD_LEVEL.

Les valeurs possibles vont de 1 à 22, la valeur par défaut est 3.

<code class="language-java">CarpetWriter<T> writer = new CarpetWriter.Builder<>(outputFile, clazz)
    .withCompressionCodec(CompressionCodecName.ZSTD)
    .build();</code>
Copier après la connexion
Copier après la connexion
Copier après la connexion

LZO

Pour référencer la configuration au niveau, le codec LZO déclare une constante : LzoCodec.LZO_COMPRESSION_LEVEL_KEY.

Les valeurs possibles vont de 1 à 9, 99 et 999, la valeur par défaut étant « 999 ».

<code class="language-java">ParquetWriter<Organization> writer = AvroParquetWriter.<Organization>builder(outputFile)
    .withSchema(new Organization().getSchema())
    .withCompressionCodec(CompressionCodecName.ZSTD)
    .build();</code>
Copier après la connexion
Copier après la connexion

GZIP

Il ne déclare aucune constante, vous devez utiliser directement la chaîne "zlib.compress.level", les valeurs possibles vont de 0 à 9, la valeur par défaut est "6".

<code class="language-java">ParquetWriter<Organization> writer = ProtoParquetWriter.<Organization>builder(outputFile)
    .withMessage(Organization.class)
    .withCompressionCodec(CompressionCodecName.ZSTD)
    .build();</code>
Copier après la connexion
Copier après la connexion

Test de performances

Pour analyser les performances de différents algorithmes de compression, j'utiliserai deux ensembles de données publics contenant différents types de données :

  • New York City Taxi Trip : contient un grand nombre de valeurs numériques et un petit nombre de valeurs de chaîne dans plusieurs colonnes. Il comporte 23 colonnes et contient 19,6 millions d'enregistrements.
  • Projet de cohésion du gouvernement italien : de nombreuses colonnes contiennent des valeurs à virgule flottante ainsi qu'un grand nombre de chaînes de texte diverses. Il comporte 91 colonnes et contient 2 millions de lignes.

Je vais évaluer certains des algorithmes de compression activés dans Parquet Java : UNCOMPRESSED, SNAPPY, GZIP, LZO, ZSTD, LZ4_RAW.

Comme prévu, j'utiliserai Carpet avec la configuration par défaut fournie par parquet-java et le niveau de compression par défaut pour chaque algorithme.

Vous pouvez trouver le code source sur GitHub, les tests ont été effectués sur un ordinateur portable équipé d'un processeur AMD Ryzen 7 4800HS et du JDK 17.

Taille du fichier

Pour comprendre les performances de chaque compression, nous utiliserons le fichier CSV équivalent comme référence.

格式 gov.it 纽约出租车
CSV 1761 MB 2983 MB
未压缩 564 MB 760 MB
SNAPPY 220 MB 542 MB
GZIP **146 MB** 448 MB
ZSTD 148 MB **430 MB**
LZ4_RAW 209 MB 547 MB
LZO 215 MB 518 MB

Parmi les deux tests, la compression utilisant GZip et Zstandard était la plus efficace.

En utilisant uniquement la technologie d'encodage Parquet, la taille du fichier peut être réduite de 25 à 32 % de la taille CSV d'origine. Avec une compression supplémentaire appliquée, elle sera réduite à 9 % à 15 % de la taille du CSV.

Écrire

Quelle surcharge la compression des informations entraîne-t-elle ?

Si on écrit trois fois la même information et calcule la moyenne des secondes, on obtient :

算法 gov.it 纽约出租车
未压缩 25.0 57.9
SNAPPY 25.2 56.4
GZIP 39.3 91.1
ZSTD 27.3 64.1
LZ4_RAW **24.9** 56.5
LZO 26.0 **56.1**

SNAPPY, LZ4 et LZO atteignent des temps similaires sans compression, tandis que ZSTD ajoute une certaine surcharge. GZIP a enregistré les pires performances, avec des temps d'écriture ralentis de 50 %.

Lire

La lecture d'un fichier est plus rapide que l'écriture car moins de calculs sont nécessaires.

Le temps en secondes pour lire toutes les colonnes du fichier est :

算法 gov.it 纽约出租车
未压缩 11.4 37.4
SNAPPY **12.5** **39.9**
GZIP 13.6 40.9
ZSTD 13.1 41.5
LZ4_RAW 12.8 41.6
LZO 13.1 41.1

Le temps de lecture est proche de celui des informations non compressées, et la surcharge de décompression est comprise entre 10 % et 20 %.

Conclusion

Aucun algorithme n'est significativement meilleur que les autres en termes de temps de lecture et d'écriture, tous sont dans une fourchette similaire. Dans la plupart des cas, la compression des informations peut compenser les gains d'espace (et le temps de transmission) perdus.

Dans ces deux cas d'utilisation, le facteur décisif dans le choix de l'un ou l'autre algorithme est probablement le taux de compression obtenu, ZSTD et Gzip étant prédominants (mais les temps d'écriture étant inférieurs).

Chaque algorithme a ses avantages, la meilleure option est donc de le tester avec vos données et de déterminer quel facteur est le plus important :

  • Minimise l'utilisation du stockage car vous stockez de grandes quantités de données rarement utilisées.
  • Réduisez le temps de génération des fichiers.
  • Réduisez le temps de lecture car les fichiers sont lus plusieurs fois.

Comme tout dans la vie, c'est un compromis et il faut voir ce qui le compense le mieux. Dans Carpet, il utilise par défaut Snappy pour la compression si vous ne configurez rien.

Détails de mise en œuvre

La valeur doit être l'une des valeurs disponibles dans l'énumération CompressionCodecName. À chaque valeur d'énumération est associé le nom de la classe qui implémente l'algorithme :

<code class="language-java">CarpetWriter<T> writer = new CarpetWriter.Builder<>(outputFile, clazz)
    .withCompressionCodec(CompressionCodecName.ZSTD)
    .build();</code>
Copier après la connexion
Copier après la connexion
Copier après la connexion

Parquet utilisera la réflexion pour instancier la classe spécifiée, qui doit implémenter l'interface CompressionCodec. Si vous regardez son code source, vous verrez qu'il se trouve dans le projet Hadoop, pas dans Parquet. Cela montre à quel point Parquet est bien couplé à Hadoop dans son implémentation Java.

Pour utiliser l'un de ces codecs, vous devez vous assurer d'avoir ajouté le JAR contenant son implémentation en tant que dépendance.

Toutes les implémentations ne sont pas présentes dans les dépendances transitives que vous avez lors de l'ajout de parquet-java, ou vous excluez peut-être les dépendances Hadoop de manière trop agressive.

Dans la dépendance org.apache.parquet:parquet-hadoop, incluez les implémentations de SnappyCodec, ZstandardCodec et Lz4RawCodec, qui importe de manière transitive les dépendances snappy-java, zstd-jni et aircompressor ainsi que les implémentations réelles de ces trois algorithmes .

Dans la dépendance hadoop-common:hadoop-common, contient l'implémentation de GzipCodec.

Où sont les implémentations de BrotliCodec et LzoCodec ? Ils ne font partie d'aucune dépendance Parquet ou Hadoop, donc si vous les utilisez sans ajouter de dépendances supplémentaires, votre application ne pourra pas utiliser de fichiers compressés dans ces formats.

  • Pour prendre en charge LZO, vous devez ajouter la dépendance org.anarres.lzo:lzo-hadoop à votre fichier pom ou gradle.
  • La situation avec Brotli est plus compliquée : la dépendance n'est pas dans Maven Central et vous devez également ajouter le dépôt JitPack.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal