Park Apache ialah format storan kolumnar yang disasarkan pada beban kerja analisis, tetapi ia boleh digunakan untuk menyimpan sebarang jenis data berstruktur, menangani pelbagai kes penggunaan.
Salah satu ciri yang paling ketara ialah keupayaan untuk memampatkan data dengan cekap menggunakan teknik pemampatan berbeza pada kedua-dua peringkat proses pemprosesan. Ini mengurangkan kos penyimpanan dan meningkatkan prestasi bacaan.
Artikel ini menerangkan pemampatan fail Parket dalam Java, menyediakan contoh penggunaan dan menganalisis prestasinya.
Tidak seperti format storan berasaskan baris tradisional, Parket menggunakan pendekatan kolumnar, membenarkan penggunaan teknik pemampatan yang lebih khusus dan cekap berdasarkan lokaliti dan lebihan nilai bagi jenis data yang sama.
Parquet menulis maklumat dalam format binari dan menggunakan pemampatan pada dua tahap berbeza, setiap satu menggunakan teknik yang berbeza:
Walaupun algoritma pemampatan dikonfigurasikan pada peringkat fail, pengekodan setiap lajur dipilih secara automatik menggunakan heuristik dalaman (sekurang-kurangnya dalam pelaksanaan parket-java).
Prestasi teknologi pemampatan yang berbeza sangat bergantung pada data anda, jadi tiada penyelesaian satu saiz yang sesuai untuk semua yang menjamin masa pemprosesan terpantas dan penggunaan storan terendah. Anda perlu melakukan ujian anda sendiri.
Konfigurasi adalah mudah dan hanya memerlukan tetapan yang jelas semasa menulis. Apabila membaca fail, Parket menemui algoritma pemampatan yang digunakan dan menggunakan algoritma penyahmampatan yang sepadan.
Dalam Permaidani dan Parket menggunakan Penampan Protokol dan Avro, untuk mengkonfigurasi algoritma pemampatan, cuma panggil pembina dengan kaedahCompressionCodec:
Permaidani
<code class="language-java">CarpetWriter<T> writer = new CarpetWriter.Builder<>(outputFile, clazz) .withCompressionCodec(CompressionCodecName.ZSTD) .build();</code>
Avro
<code class="language-java">ParquetWriter<Organization> writer = AvroParquetWriter.<Organization>builder(outputFile) .withSchema(new Organization().getSchema()) .withCompressionCodec(CompressionCodecName.ZSTD) .build();</code>
Penimbal Protokol
<code class="language-java">ParquetWriter<Organization> writer = ProtoParquetWriter.<Organization>builder(outputFile) .withMessage(Organization.class) .withCompressionCodec(CompressionCodecName.ZSTD) .build();</code>
Nilai mestilah salah satu nilai yang tersedia dalam penghitungan CompressionCodecName: UNCOMPRESSED, SNAPPY, GZIP, LZO, BROTLI, LZ4, ZSTD dan LZ4_RAW (LZ4 ditamatkan, LZ4_RAW harus digunakan).
Sesetengah algoritma mampatan menyediakan cara untuk memperhalusi tahap mampatan. Tahap ini biasanya berkaitan dengan berapa banyak usaha yang mereka perlukan untuk mencari corak berulang; semakin tinggi tahap mampatan, lebih banyak masa dan ingatan yang diperlukan oleh proses mampatan.
Walaupun ia disertakan dengan nilai lalai, ia boleh diubah suai menggunakan mekanisme konfigurasi generik Parket, walaupun menggunakan kekunci berbeza untuk setiap codec.
Selain itu, nilai untuk dipilih adalah tidak standard dan bergantung pada setiap codec, jadi anda mesti merujuk kepada dokumentasi untuk setiap algoritma untuk memahami perkara yang ditawarkan oleh setiap tahap.
ZSTD
Untuk konfigurasi tahap rujukan, codec ZSTD mengisytiharkan pemalar: ZstandardCodec.PARQUET_COMPRESS_ZSTD_LEVEL
.
Nilai yang mungkin berjulat dari 1 hingga 22, nilai lalai ialah 3.
<code class="language-java">CarpetWriter<T> writer = new CarpetWriter.Builder<>(outputFile, clazz) .withCompressionCodec(CompressionCodecName.ZSTD) .build();</code>
LZO
Untuk konfigurasi tahap rujukan, codec LZO mengisytiharkan pemalar: LzoCodec.LZO_COMPRESSION_LEVEL_KEY
.
Nilai yang mungkin berjulat dari 1 hingga 9, 99 dan 999, dengan nilai lalai ialah '999'.
<code class="language-java">ParquetWriter<Organization> writer = AvroParquetWriter.<Organization>builder(outputFile) .withSchema(new Organization().getSchema()) .withCompressionCodec(CompressionCodecName.ZSTD) .build();</code>
GZIP
Ia tidak mengisytiharkan sebarang pemalar, anda mesti menggunakan rentetan "zlib.compress.level" secara langsung, nilai kemungkinan antara 0 hingga 9, nilai lalai ialah "6".
<code class="language-java">ParquetWriter<Organization> writer = ProtoParquetWriter.<Organization>builder(outputFile) .withMessage(Organization.class) .withCompressionCodec(CompressionCodecName.ZSTD) .build();</code>
Untuk menganalisis prestasi algoritma pemampatan yang berbeza, saya akan menggunakan dua set data awam yang mengandungi jenis data yang berbeza:
Saya akan menilai beberapa algoritma mampatan yang didayakan dalam Parquet Java: UNCOMPRESSED, SNAPPY, GZIP, LZO, ZSTD, LZ4_RAW.
Seperti yang dijangkakan, saya akan menggunakan Carpet dengan konfigurasi lalai yang disediakan oleh parket-java dan tahap mampatan lalai untuk setiap algoritma.
Anda boleh mencari kod sumber di GitHub, ujian telah dilakukan pada komputer riba dengan CPU AMD Ryzen 7 4800HS dan JDK 17.
Untuk memahami prestasi setiap pemampatan, kami akan menggunakan fail CSV yang setara sebagai rujukan.
格式 | 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 |
Daripada dua ujian, pemampatan menggunakan GZip dan Zstandard adalah yang paling berkesan.
Hanya menggunakan teknologi pengekodan Parket, saiz fail boleh dikecilkan kepada 25%-32% daripada saiz CSV asal. Dengan pemampatan tambahan digunakan, ia akan dikurangkan kepada 9% hingga 15% daripada saiz CSV.
Berapa banyak overhed yang dibawa oleh maklumat memampatkan?
Jika kita menulis maklumat yang sama tiga kali dan mengira purata saat, kita mendapat:
算法 | 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 dan LZO mencapai masa yang sama tanpa pemampatan, manakala ZSTD menambah beberapa overhed. GZIP mempunyai prestasi yang paling teruk, dengan masa tulis menjadi perlahan sebanyak 50%.
Membaca fail lebih pantas daripada menulis kerana kurang pengiraan diperlukan.
Masa dalam beberapa saat untuk membaca semua lajur dalam fail ialah:
算法 | 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 |
Masa membaca adalah hampir dengan maklumat yang tidak dimampatkan dan overhed penyahmampatan adalah antara 10% dan 20%.
Tiada algoritma yang jauh lebih baik daripada yang lain dari segi masa baca dan tulis, semuanya berada dalam julat yang sama. Dalam kebanyakan kes, memampatkan maklumat boleh menggantikan penjimatan ruang (dan penghantaran) masa yang hilang.
Dalam kedua-dua kes penggunaan ini, faktor penentu dalam memilih satu atau algoritma lain mungkin adalah nisbah mampatan yang dicapai, dengan ZSTD dan Gzip menonjol (tetapi masa penulisan adalah lebih rendah).
Setiap algoritma mempunyai kelebihannya, jadi pilihan terbaik ialah mengujinya dengan data anda dan pertimbangkan faktor mana yang lebih penting:
Seperti segala-galanya dalam kehidupan, ia adalah satu pertukaran dan anda perlu melihat apa yang terbaik mengimbanginya. Dalam Permaidani, secara lalai ia menggunakan Snappy untuk pemampatan jika anda tidak mengkonfigurasi apa-apa.
Nilai mestilah salah satu nilai yang tersedia dalam penghitungan CompressionCodecName. Dikaitkan dengan setiap nilai penghitungan ialah nama kelas yang melaksanakan algoritma:
<code class="language-java">CarpetWriter<T> writer = new CarpetWriter.Builder<>(outputFile, clazz) .withCompressionCodec(CompressionCodecName.ZSTD) .build();</code>
Parquet akan menggunakan pantulan untuk membuat contoh kelas yang ditentukan, yang mesti melaksanakan antara muka CompressionCodec. Jika anda melihat kod sumbernya, anda akan melihat bahawa ia berada dalam projek Hadoop, bukan Parket. Ini menunjukkan sejauh mana Parket digandingkan dengan Hadoop dalam pelaksanaan Javanya.
Untuk menggunakan salah satu codec ini, anda mesti memastikan bahawa anda telah menambahkan JAR yang mengandungi pelaksanaannya sebagai kebergantungan.
Tidak semua pelaksanaan terdapat dalam kebergantungan transitif yang anda miliki semasa menambah parket-java, atau anda mungkin mengecualikan kebergantungan Hadoop secara terlalu agresif.
Dalam kebergantungan org.apache.parquet:parquet-hadoop, sertakan pelaksanaan SnappyCodec, ZstandardCodec dan Lz4RawCodec, yang secara transitif mengimport kebergantungan snappy-java, zstd-jni dan pemampat udara bersama-sama dengan pelaksanaan sebenar ketiga-tiga algoritma ini .
Dalam pergantungan hadoop-common:hadoop-common, mengandungi pelaksanaan GzipCodec.
Di manakah pelaksanaan BrotliCodec dan LzoCodec? Ia tidak berada dalam mana-mana kebergantungan Parket atau Hadoop, jadi jika anda menggunakannya tanpa menambah kebergantungan tambahan, aplikasi anda tidak akan dapat menggunakan fail yang dimampatkan dalam format tersebut.
Atas ialah kandungan terperinci Algoritma mampatan dalam Parquet Java. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!