Kompresi memperkecil ukuran data dengan memanfaatkan pola yang berulang, dengan biaya berupa waktu CPU saat memadatkan dan membukanya. Pada pipeline data, pilihan codec menentukan ruang simpan, kecepatan transfer, dan kecepatan query sekaligus. Topik ini membahas pertimbangan memilih gzip atau zstd dari sisi rasio dan kecepatan, beserta interaksi kompresi dengan format kolom seperti Parquet.
Peran kompresi di pipeline#
Kompresi memetakan byte data ke bentuk yang lebih kecil dengan mengenali pola berulang. Alat yang memadatkan dan membuka kembali data tersebut disebut codec, yakni satu alat yang berisi encoder dan decoder sekaligus. Keputusannya selalu merupakan pertimbangan, karena rasio yang lebih tinggi biasanya dibayar dengan waktu CPU yang lebih lama. Tidak ada codec yang unggul pada semua sisi, sehingga pilihannya mengikuti pola kerja pipeline.
Di dalam pipeline, kompresi bekerja di tiga tempat sekaligus, yaitu saat data disimpan di lake, saat data berpindah jaringan, dan saat data dibaca query. Data lake menyimpan tabel dalam volume besar sehingga selisih rasio berlipat menjadi biaya nyata. Sementara itu, query yang membaca berkas terkompresi menukar CPU dengan waktu baca jaringan yang lebih singkat, dan pertukaran ini biasanya menguntungkan karena data analitik terkompresi dengan baik.
Mengompresi CSV dengan modul gzip#
Modul gzip bawaan Python mengompresi data dengan algoritma DEFLATE pada level 1 sampai 9, dan level yang lebih tinggi menghasilkan berkas lebih kecil dengan waktu lebih lama.
import gzip
import os
# 1. susun CSV sampel 20.000 baris dengan pola yang berulang
baris = ["id_pengukuran,sensor,suhu_c,kelembapan\n"]
for i in range(20000):
suhu = 24 + (i % 8) * 0.5
kelembapan = 55 + (i % 10)
baris.append(f"{i:06d},Ruang-{i % 3 + 1},{suhu},{kelembapan}\n")
data = "".join(baris).encode("utf-8")
with open("sensor.csv", "wb") as f:
f.write(data)
# 2. kompres dengan level 9, yang paling padat
with gzip.open("sensor.csv.gz", "wb", compresslevel=9) as f:
f.write(data)
# 3. bandingkan ukurannya
asli = os.path.getsize("sensor.csv")
padat = os.path.getsize("sensor.csv.gz")
print(f"ukuran sensor.csv : {asli} byte")
print(f"ukuran sensor.csv.gz : {padat} byte")
print(f"rasio : {asli / padat:.1f}x")
# 4. berkas gzip tetap terbaca seperti CSV biasa
with gzip.open("sensor.csv.gz", "rt", encoding="utf-8") as f:
print("baris pertama :", f.readline().rstrip())ukuran sensor.csv : 460039 byte
ukuran sensor.csv.gz : 57711 byte
rasio : 8.0x
baris pertama : id_pengukuran,sensor,suhu_c,kelembapanData sampelnya sengaja dibangun dari pola yang berulang sehingga rasinya tinggi, dan data nyata dengan lebih banyak variasi akan menghasilkan rasio yang lebih rendah. Pembacaan kembali pada langkah keempat menunjukkan bahwa berkas .gz tetap terbaca seperti CSV biasa melalui mode teks gzip, sehingga proses di hilir tidak perlu tahu bahwa berkasnya terkompresi. Satu kebiasaan perlu dijaga, yaitu mencantumkan level yang dipakai. Dua berkas hasil level yang berbeda tidak layak dibandingkan, karena ukurannya berbeda bukan karena data, melainkan karena parameternya.
zstd sebagai alternatif#
zstd, atau Zstandard, adalah codec modern yang mengatur pertimbangan rasio dan kecepatan lewat level 1 sampai 22. Rentang levelnya lebih lebar daripada gzip, mulai dari level terendah yang sangat cepat sampai level tertinggi yang menyusutkan berkas jauh lebih rapat. Kekuatan utamanya ada pada dekompresi yang tetap cepat di seluruh level, sehingga biaya level tinggi lebih dirasakan pada sisi penulis daripada pada sisi pembaca.
Pemakaiannya lewat CLI tampak seperti berikut. Perintahnya memerlukan CLI zstd yang dipasang terpisah, sehingga potongan ini tidak dijalankan dan hanya sebagai ilustrasi.
# tidak-dijalankan
# kompres dengan level default
zstd sensor.csv
# kompres dengan level tinggi untuk ukuran terkecil
zstd -19 sensor.csv
# dekompresi kembali menjadi CSV
zstd -d sensor.csv.zstHasilnya berupa berkas .zst yang berdampingan dengan CSV aslinya, dan parameter -19 menunjukkan level kompresi yang dipilih. Alur kerjanya sama persis dengan gzip pada CLI, hanya nama alat dan ekstensinya yang berbeda. Perbedaan yang paling terasa ada pada waktu eksekusi dan ukuran akhirnya, yang keduanya bergantung pada level yang dipilih.
gzip versus zstd#
Perbandingan keduanya dirangkum dalam tabel kualitatif berikut, tanpa angka tolok ukur karena hasilnya bergantung pada data dan perangkat yang dipakai.
| Aspek | gzip | zstd |
|---|---|---|
| Rasio kompresi | baik | biasanya lebih tinggi pada level sebanding |
| Kecepatan kompresi | sedang | cepat, terutama pada level rendah |
| Kecepatan dekompresi | cepat | cepat pada seluruh level |
| Rentang level | 1 sampai 9 | 1 sampai 22 |
| Dukungan ekosistem | sangat luas sebagai standar lama | didukung luas pada format kolom dan alat modern |
Aturan praktisnya, gzip dipilih bila kompatibilitas dengan alat lama menjadi syarat, sedangkan zstd dipilih untuk pipeline baru yang bebas kendala tersebut. Level menengah pada keduanya biasanya sudah memadai, dan level tertinggi hanya perlu bila ruang simpan jauh lebih mahal daripada waktu CPU. Keputusan terbaik tetap berasal dari uji coba pada sampel data nyata milik pipeline itu sendiri.
Kompresi dan format kolom#
Pada Parquet, kompresi bekerja di atas encoding kolom, sehingga interaksinya dengan data berbeda dari CSV. Parquet menerapkan encoding seperti dictionary dan run-length pada setiap column chunk, kemudian codec seperti snappy, gzip, atau zstd memadatkan hasil encoding itu. Nilai yang berulang menjadi sangat efektif dipadatkan karena sudah diringkas oleh encoding sebelum codec bekerja.
CSV terkompresi berperilaku berbeda. gzip memadatkan berkasnya sebagai satu aliran, sehingga membaca satu kolom tetap harus membuka seluruh berkas. Parquet memadatkan per page, sehingga bagian yang tidak dibaca tidak perlu dibuka, dan pilihan codec dapat berbeda antar berkas maupun antar kolom. Perbedaan ini membuat kombinasi Parquet dengan codec modern menjadi pilihan bawaan untuk tabel analitik yang besar.
Pilihan codec Parquet mengikuti pola yang sama dengan pilihan kompresi berkas. snappy menjadi pilihan bawaan karena cepat, gzip dipilih bila rasio diutamakan dengan biaya CPU, dan zstd dipilih bila rasio tinggi serta dekompresi cepat dibutuhkan bersamaan. Pilihan yang sama juga dapat dievaluasi ulang seiring data tumbuh, karena codec dapat diganti saat tabel ditulis ulang.
Kesalahan umum#
Kesalahan kompresi jarang menghentikan pipeline, tetapi ketiganya memboroskan ruang dan CPU dalam waktu yang lama sebelum terlihat.
- Membandingkan codec pada data sampel yang berbeda atau level yang berbeda. Kesimpulannya menggambarkan perbedaan data, bukan perbedaan codec. Perbaikannya adalah menguji pada sampel data nyata dengan level yang dicantumkan.
- Menumpuk kompresi, misalnya berkas
.gzdipadatkan lagi menjadi.zst. Ukurannya hampir tidak turun karena pola berulang sudah habis dipakai. Perbaikannya adalah membuka kompresi lama terlebih dahulu atau menyimpan hanya satu bentuk terkompresi. - Memilih level tertinggi untuk data yang ditulis setiap jam. Waktu CPU berlipat padahal selisih ukurannya kecil. Perbaikannya adalah menggunakan level menengah dan menyisakan level tinggi untuk arsip.
Ringkasan#
- Kompresi memperdagangkan waktu CPU dengan ukuran simpan dan transfer, sehingga pilihan codec harus mengikuti pola tulis dan baca pipeline.
- gzip menawarkan kompatibilitas terluas dengan level 1 sampai 9, sedangkan zstd menawarkan rentang level yang lebih lebar dengan dekompresi yang tetap cepat.
- Pada Parquet, codec memadatkan hasil encoding kolom per page, sehingga pilihan codec dan tata letak bekerja bersama, bukan saling menggantikan.
Referensi#
- Zstandard — Meta di GitHub — Repositori resmi zstd beserta penjelasan level kompresinya.
- Dokumentasi modul gzip — Python Software Foundation — Referensi parameter compresslevel yang dipakai pada contoh.