Heim > Java > javaLernprogramm > Komprimierungsalgorithmen in Parquet Java

Komprimierungsalgorithmen in Parquet Java

Mary-Kate Olsen
Freigeben: 2025-01-20 18:04:12
Original
1006 Leute haben es durchsucht

Compression algorithms in Parquet Java

Apache Parquet ist ein spaltenorientiertes Speicherformat, das auf analytische Arbeitslasten abzielt, aber es kann zum Speichern jeder Art von strukturierten Daten verwendet werden und eine Vielzahl von Anwendungsfällen abdecken.

Eines der bemerkenswertesten Merkmale ist die Fähigkeit, Daten mithilfe verschiedener Komprimierungstechniken in beiden Phasen des Verarbeitungsprozesses effizient zu komprimieren. Dies reduziert die Speicherkosten und verbessert die Leseleistung.

In diesem Artikel wird die Dateikomprimierung von Parquet in Java erläutert, Anwendungsbeispiele bereitgestellt und die Leistung analysiert.

Kompressionstechnologie

Im Gegensatz zu herkömmlichen zeilenbasierten Speicherformaten verwendet Parquet einen spaltenbasierten Ansatz, der die Verwendung spezifischerer und effizienterer Komprimierungstechniken ermöglicht, die auf Lokalität und Wertredundanz desselben Datentyps basieren.

Parquet schreibt Informationen im Binärformat und wendet die Komprimierung auf zwei verschiedenen Ebenen an, wobei jede eine andere Technik verwendet:

  • Beim Schreiben des Werts der Spalte wird der Codierungstyp entsprechend den Eigenschaften des Anfangswerts adaptiv ausgewählt: Wörterbuchcodierung, Lauflängencodierung, Bitpackung, inkrementelle Codierung usw.
  • Immer wenn eine bestimmte Anzahl von Bytes erreicht ist (Standard ist 1 MB), wird eine Seite erstellt und der Binärblock mithilfe eines vom Programmierer konfigurierbaren Algorithmus komprimiert (keine Komprimierung, GZip, Snappy, LZ4, ZSTD usw.).

Obwohl der Komprimierungsalgorithmus auf Dateiebene konfiguriert wird, wird die Kodierung jeder Spalte automatisch mithilfe einer internen Heuristik ausgewählt (zumindest in der Parquet-Java-Implementierung).

Die Leistung verschiedener Komprimierungstechnologien hängt stark von Ihren Daten ab, daher gibt es keine einheitliche Lösung, die die schnellste Verarbeitungszeit und den niedrigsten Speicherverbrauch garantiert. Sie müssen Ihre eigenen Tests durchführen.

Code

Die Konfiguration ist einfach und erfordert nur eine explizite Einstellung beim Schreiben. Beim Lesen einer Datei erkennt Parquet, welcher Komprimierungsalgorithmus verwendet wird, und wendet den entsprechenden Dekomprimierungsalgorithmus an.

Algorithmus oder Codec konfigurieren

In Teppich und Parkett mit Protokollpuffern und Avro rufen Sie zum Konfigurieren des Komprimierungsalgorithmus einfach die withCompressionCodec-Methode des Builders auf:

Teppich

CarpetWriter<T> writer = new CarpetWriter.Builder<>(outputFile, clazz)
    .withCompressionCodec(CompressionCodecName.ZSTD)
    .build();
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Avro

ParquetWriter<Organization> writer = AvroParquetWriter.<Organization>builder(outputFile)
    .withSchema(new Organization().getSchema())
    .withCompressionCodec(CompressionCodecName.ZSTD)
    .build();
Nach dem Login kopieren
Nach dem Login kopieren

Protokollpuffer

ParquetWriter<Organization> writer = ProtoParquetWriter.<Organization>builder(outputFile)
    .withMessage(Organization.class)
    .withCompressionCodec(CompressionCodecName.ZSTD)
    .build();
Nach dem Login kopieren
Nach dem Login kopieren

Der Wert muss einer der in der Aufzählung „CompressionCodecName“ verfügbaren Werte sein: UNCOMPRESSED, SNAPPY, GZIP, LZO, BROTLI, LZ4, ZSTD und LZ4_RAW (LZ4 ist veraltet, LZ4_RAW sollte verwendet werden).

Komprimierungsstufe

Einige Komprimierungsalgorithmen bieten eine Möglichkeit zur Feinabstimmung der Komprimierungsstufe. Diese Stufe hängt in der Regel davon ab, wie viel Aufwand sie in die Suche nach sich wiederholenden Mustern investieren müssen. Je höher die Komprimierungsstufe, desto mehr Zeit und Speicher erfordert der Komprimierungsprozess.

Obwohl sie mit Standardwerten geliefert werden, können sie mit dem generischen Konfigurationsmechanismus von Parquet geändert werden, allerdings unter Verwendung unterschiedlicher Schlüssel für jeden Codec.

Darüber hinaus sind die auszuwählenden Werte nicht standardisiert und hängen von jedem Codec ab. Daher müssen Sie die Dokumentation für jeden Algorithmus konsultieren, um zu verstehen, was jede Ebene bietet.

ZSTD

Zur Referenzebenenkonfiguration deklariert der ZSTD-Codec eine Konstante: ZstandardCodec.PARQUET_COMPRESS_ZSTD_LEVEL.

Mögliche Werte liegen zwischen 1 und 22, der Standardwert ist 3.

CarpetWriter<T> writer = new CarpetWriter.Builder<>(outputFile, clazz)
    .withCompressionCodec(CompressionCodecName.ZSTD)
    .build();
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

LZO

Zur Referenzebenenkonfiguration deklariert der LZO-Codec eine Konstante: LzoCodec.LZO_COMPRESSION_LEVEL_KEY.

Mögliche Werte reichen von 1 bis 9, 99 und 999, wobei der Standardwert „999“ ist.

ParquetWriter<Organization> writer = AvroParquetWriter.<Organization>builder(outputFile)
    .withSchema(new Organization().getSchema())
    .withCompressionCodec(CompressionCodecName.ZSTD)
    .build();
Nach dem Login kopieren
Nach dem Login kopieren

GZIP

Es werden keine Konstanten deklariert, Sie müssen die Zeichenfolge „zlib.compress.level“ direkt verwenden, mögliche Werte reichen von 0 bis 9, der Standardwert ist „6“.

ParquetWriter<Organization> writer = ProtoParquetWriter.<Organization>builder(outputFile)
    .withMessage(Organization.class)
    .withCompressionCodec(CompressionCodecName.ZSTD)
    .build();
Nach dem Login kopieren
Nach dem Login kopieren

Leistungstest

Um die Leistung verschiedener Komprimierungsalgorithmen zu analysieren, verwende ich zwei öffentliche Datensätze, die unterschiedliche Datentypen enthalten:

  • New York City Taxi Trip: Enthält eine große Anzahl numerischer und eine kleine Anzahl Zeichenfolgenwerte in mehreren Spalten. Es hat 23 Spalten und enthält 19,6 Millionen Datensätze.
  • Kohäsionsprojekt der italienischen Regierung: Viele Spalten enthalten Gleitkommawerte sowie eine große Anzahl verschiedener Textzeichenfolgen. Es hat 91 Spalten und enthält 2 Millionen Zeilen.

Ich werde einige der in Parquet Java aktivierten Komprimierungsalgorithmen bewerten: UNCOMPRESSED, SNAPPY, GZIP, LZO, ZSTD, LZ4_RAW.

Wie erwartet verwende ich Carpet mit der von parquet-java bereitgestellten Standardkonfiguration und der Standardkomprimierungsstufe für jeden Algorithmus.

Den Quellcode finden Sie auf GitHub, der Test wurde auf einem Laptop mit einer AMD Ryzen 7 4800HS CPU und JDK 17 durchgeführt.

Dateigröße

Um die Leistung jeder Komprimierung zu verstehen, verwenden wir die entsprechende CSV-Datei als Referenz.

格式gov.it纽约出租车
CSV1761 MB2983 MB
未压缩564 MB760 MB
SNAPPY220 MB542 MB
GZIP**146 MB**448 MB
ZSTD148 MB**430 MB**
LZ4_RAW209 MB547 MB
LZO215 MB518 MB

Von den beiden Tests war die Komprimierung mit GZip und Zstandard am effizientesten.

Wenn nur die Parquet-Kodierungstechnologie verwendet wird, kann die Dateigröße auf 25–32 % der ursprünglichen CSV-Größe reduziert werden. Bei zusätzlicher Komprimierung wird sie auf 9 % bis 15 % der CSV-Größe reduziert.

Schreiben

Wie viel Overhead bringt die Komprimierung von Informationen mit sich?

Wenn wir die gleichen Informationen dreimal schreiben und die durchschnittlichen Sekunden berechnen, erhalten wir:

算法gov.it纽约出租车
未压缩25.057.9
SNAPPY25.256.4
GZIP39.391.1
ZSTD27.364.1
LZ4_RAW**24.9**56.5
LZO26.0**56.1**

SNAPPY, LZ4 und LZO erreichen ähnliche Zeiten wie bei keiner Komprimierung, während ZSTD etwas Overhead verursacht. GZIP hatte die schlechteste Leistung, die Schreibzeiten verlangsamten sich um 50 %.

Lesen

Das Lesen einer Datei ist schneller als das Schreiben, da weniger Rechenaufwand erforderlich ist.

Die Zeit in Sekunden zum Lesen aller Spalten in der Datei beträgt:

算法gov.it纽约出租车
未压缩11.437.4
SNAPPY**12.5****39.9**
GZIP13.640.9
ZSTD13.141.5
LZ4_RAW12.841.6
LZO13.141.1

Die Lesezeit liegt nahe an der von unkomprimierten Informationen und der Dekomprimierungsaufwand liegt zwischen 10 % und 20 %.

Fazit

Kein Algorithmus ist hinsichtlich der Lese- und Schreibzeiten deutlich besser als die anderen, alle liegen in einem ähnlichen Bereich. In den meisten Fällen kann die Komprimierung von Informationen die Platzersparnis (und die verlorene Übertragungszeit) ausgleichen.

In diesen beiden Anwendungsfällen ist wahrscheinlich das erreichte Komprimierungsverhältnis der entscheidende Faktor für die Wahl des einen oder anderen Algorithmus, wobei ZSTD und Gzip im Vordergrund stehen (aber die Schreibzeiten sind schlechter).

Jeder Algorithmus hat seine Vorteile, daher ist es am besten, ihn mit Ihren Daten zu testen und zu überlegen, welcher Faktor wichtiger ist:

  • Minimiert die Speichernutzung, da Sie große Mengen selten verwendeter Daten speichern.
  • Minimieren Sie die Dateigenerierungszeit.
  • Minimieren Sie die Lesezeit, da Dateien mehrmals gelesen werden.

Wie alles im Leben ist es ein Kompromiss und man muss sehen, was ihn am besten ausgleicht. In Carpet wird standardmäßig Snappy zur Komprimierung verwendet, wenn Sie nichts konfigurieren.

Implementierungsdetails

Der Wert muss einer der in der Aufzählung „CompressionCodecName“ verfügbaren Werte sein. Jedem Aufzählungswert ist der Name der Klasse zugeordnet, die den Algorithmus implementiert:

CarpetWriter<T> writer = new CarpetWriter.Builder<>(outputFile, clazz)
    .withCompressionCodec(CompressionCodecName.ZSTD)
    .build();
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Parquet verwendet Reflektion, um die angegebene Klasse zu instanziieren, die die CompressionCodec-Schnittstelle implementieren muss. Wenn Sie sich den Quellcode ansehen, werden Sie feststellen, dass er sich im Hadoop-Projekt und nicht in Parquet befindet. Dies zeigt, wie gut Parquet in seiner Java-Implementierung an Hadoop gekoppelt ist.

Um einen dieser Codecs zu verwenden, müssen Sie sicherstellen, dass Sie das JAR, das seine Implementierung enthält, als Abhängigkeit hinzugefügt haben.

In den transitiven Abhängigkeiten, die Sie beim Hinzufügen von Parquet-Java haben, sind nicht alle Implementierungen vorhanden, oder Sie schließen Hadoop-Abhängigkeiten möglicherweise zu aggressiv aus.

In der Abhängigkeit org.apache.parquet:parquet-hadoop sind Implementierungen von SnappyCodec, ZstandardCodec und Lz4RawCodec enthalten, die die Abhängigkeiten snappy-java, zstd-jni und aircompressor zusammen mit den tatsächlichen Implementierungen dieser drei Algorithmen transitiv importieren .

Enthält in der Abhängigkeit hadoop-common:hadoop-common die Implementierung von GzipCodec.

Wo sind die Implementierungen von BrotliCodec und LzoCodec? Sie befinden sich in keinen Parquet- oder Hadoop-Abhängigkeiten. Wenn Sie sie also verwenden, ohne zusätzliche Abhängigkeiten hinzuzufügen, kann Ihre Anwendung keine in diesen Formaten komprimierten Dateien verwenden.

  • Um LZO zu unterstützen, müssen Sie die Abhängigkeit org.anarres.lzo:lzo-hadoop zu Ihrer POM- oder Gradle-Datei hinzufügen.
  • Bei Brotli ist die Situation komplizierter: Die Abhängigkeit liegt nicht in Maven Central und Sie müssen auch das JitPack-Repository hinzufügen.

Das obige ist der detaillierte Inhalt vonKomprimierungsalgorithmen in Parquet Java. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage