- ClickHouse memperkenalkan tipe JSON baru yang menempatkan nilai per path JSON di penyimpanan kolumnar sungguhan, untuk menghindari bottleneck akibat menyimpan dokumen JSON sebagai string lalu mem-parsing-nya setiap kali
- Inti implementasinya adalah tipe Variant dan Dynamic; meski path JSON yang sama berisi tipe berbeda seperti integer, string, atau array, nilainya tidak dipaksa disatukan ke tipe umum minimum
- Nilai default
max_dynamic_paths adalah 1024 dan max_dynamic_types adalah 32, membatasi jumlah subkolom dan file per tipe untuk mengendalikan peningkatan file descriptor dan biaya merge
- Cara penyimpanan per path dapat disesuaikan dengan type hint,
SKIP, dan SKIP REGEXP, sementara nilai dapat dibaca dengan sintaks subkolom seperti C.a.b
- Tipe baru ini bertujuan menggantikan
Object('json') yang sudah deprecated, dan perbaikan untuk menggunakan path key JSON sebagai primary key atau data-skipping index masih ada di roadmap
Tantangan menyesuaikan JSON dengan penyimpanan kolumnar
- JSON digunakan sebagai format umum untuk menangani data semi-terstruktur dan tidak terstruktur dalam log, observability, streaming data real-time, penyimpanan aplikasi mobile, dan pipeline machine learning
- ClickHouse adalah database yang benar-benar berorientasi kolom, menyimpan tabel sebagai kumpulan file data kolom di disk untuk menjalankan kompresi serta filter dan agregasi terv Ditaksikan
- Untuk memperoleh performa yang sama pada JSON, alih-alih menyimpan dokumen di kolom string lalu mem-parsing-nya belakangan, nilai dari setiap path JSON unik harus disimpan seperti kolom
Empat batasan yang ditangani tipe JSON baru
-
Penyimpanan kolumnar per path
- Nilai per path JSON juga harus dapat dikompresi seperti kolom biasa, misalnya tipe numerik, serta difilter dan diagregasi secara terv Difaktorkan
-
Tipe yang berubah secara dinamis
- Path JSON yang sama
a dapat berisi tipe berbeda seperti integer, floating point, atau array
- ClickHouse tidak dapat mengetahuinya terlebih dahulu, dan tipe-tipe tersebut mungkin tidak kompatibel satu sama lain; jika digabungkan ke tipe umum minimum, informasi dapat hilang
-
Mencegah ledakan file kolom
- Jika file kolom baru dibuat untuk setiap path JSON baru, jumlah file disk akan melonjak pada data dengan banyak key unik
- File descriptor menggunakan memori, dan makin banyak file yang harus diproses juga memengaruhi performa merge
-
Penyimpanan padat untuk key yang sparse
- Saat ada banyak key JSON yang unik tetapi sparse, sistem tidak boleh berulang kali menyimpan
NULL atau nilai default untuk setiap baris yang tidak memiliki nilai
- Hanya nilai nyata yang harus disimpan secara padat agar tetap dapat diskalakan untuk analisis skala PB
Tipe Variant: fondasi yang tidak memaksa penyatuan tipe
- Tipe data Variant adalah fitur independen yang dapat digunakan terpisah dari JSON, dan memungkinkan penyimpanan serta pembacaan nilai dengan tipe data berbeda dalam satu kolom tabel
- Kolom ClickHouse yang sudah ada memiliki tipe tetap, dan nilai yang dimasukkan harus bertipe tersebut atau dikonversi secara implisit
- Kolom
Nullable menggunakan file mask NULL selain file nilai
Array menyimpan ukuran array di file terpisah dan menghitung offset darinya
- Kolom Variant menyimpan nilai dengan tipe konkret yang sama dalam subkolom per tipe
- Contoh: semua nilai
Int64 disimpan di C.Int64.bin, semua nilai String disimpan di C.String.bin
- Tipe apa yang digunakan setiap baris dilacak dengan kolom discriminator
UInt8
- Nilai discriminator adalah indeks dalam daftar nama tipe yang diurutkan
- Discriminator
255 adalah nilai cadangan untuk NULL
- Karena desain ini, Variant dapat memiliki hingga 255 tipe konkret
- File data per tipe memakai struktur penyimpanan padat yang hanya berisi baris yang memiliki nilai
- File per tipe tidak menyimpan nilai
NULL
- Untuk menemukan posisi baris pada file tipe nyata dari baris discriminator, digunakan kolom offset
UInt64 di memori
- Offset ini tidak disimpan di disk dan dapat dibuat seketika dari file kolom discriminator
- Variant mendukung nesting arbitrer
- Urutan tipe pada
Variant(T1, T2) dan Variant(T2, T1) memiliki makna yang sama
- Variant dapat dimasukkan lagi di dalam Variant
- Nilai tipe bersarang tertentu dibaca dengan menambahkan nama tipe seperti subkolom
Tipe Dynamic: menyimpan tanpa mengetahui daftar tipe terlebih dahulu
- Tipe Dynamic adalah fitur independen yang diimplementasikan di atas Variant, dan dapat digunakan di luar konteks JSON
- Dynamic menambahkan dua kemampuan pada Variant
- Menyimpan nilai dengan tipe arbitrer dalam satu kolom tanpa perlu menentukan daftar tipe terlebih dahulu
- Membatasi jumlah tipe yang disimpan sebagai file data kolom terpisah
- Cara penyimpanan internalnya sama seperti Variant, tetapi ditambah file
C.dynamic_structure.bin
- File ini berisi daftar tipe yang disimpan sebagai subkolom dan statistik ukuran file data kolom per tipe
- Metadata tersebut digunakan untuk pembacaan subkolom dan merge data part
Dynamic(max_types=N) membatasi jumlah tipe yang akan disimpan sebagai file terpisah
0 <= N < 255
- Nilai defaultnya adalah 32
- Saat batas tercapai, nilai tipe sisanya disimpan dalam satu file kolom seperti
C.SharedVariant.bin
- Tipe file ini adalah
String
- Setiap baris berisi nilai string berstruktur
<binary_encoded_data_type><binary_value>
- Nilai dari berbagai tipe dapat disimpan dalam satu file kolom lalu dibaca kembali
- Dynamic juga dapat membaca nilai tipe tertentu dengan menggunakan nama tipe sebagai subkolom, seperti Variant
Deklarasi tipe JSON dan struktur penyimpanan
- Tipe JSON baru menyimpan objek JSON dengan struktur arbitrer dan memungkinkan setiap nilai JSON dibaca sebagai subkolom berbasis path
- Deklarasi tipe dapat memiliki parameter dan hint opsional
<column_name> JSON(
max_dynamic_paths=N,
max_dynamic_types=M,
some.path TypeName,
SKIP path.to.skip,
SKIP REGEXP 'paths_regexp')
max_dynamic_paths
- Nilai defaultnya adalah 1024
- Menentukan jumlah path key JSON yang akan disimpan sebagai subkolom terpisah
- Path yang melewati batas disimpan bersama dalam satu subkolom berstruktur khusus
max_dynamic_types
- Nilai defaultnya adalah 32
- Rentang nilainya dari
0 sampai 254
- Menentukan jumlah tipe data pada satu kolom path key JSON yang akan disimpan sebagai file data kolom terpisah
- Tipe baru yang melewati batas disimpan bersama dalam satu file data kolom khusus
some.path TypeName
- Ini adalah type hint untuk path JSON tertentu
- Path tersebut selalu disimpan sebagai subkolom dengan tipe yang ditentukan, sehingga memberikan jaminan performa
SKIP path.to.skip
- Melewati path JSON tertentu saat parsing
- Path tersebut tidak disimpan di kolom JSON
- Jika path yang ditentukan adalah objek JSON bersarang, seluruh objek bersarang tersebut dilewati
SKIP REGEXP 'path_regexp'
- Melewati path yang cocok dengan regular expression saat parsing JSON
- Path yang cocok tidak disimpan di kolom JSON
Cara membaca path JSON seperti kolom
- Setiap nilai leaf path unik dari kolom JSON disimpan di disk dengan salah satu dari dua cara
- Path yang memiliki type hint disimpan sebagai file data kolom biasa
- Path dengan tipe yang dapat berubah secara dinamis disimpan sebagai subkolom Dynamic
- Tipe JSON menggunakan file khusus bernama
object_structure
- Berisi metadata untuk path dinamis
- Berisi statistik nilai non-null dari setiap path dinamis
- Digunakan untuk pembacaan subkolom dan merge data part
- Ledakan file kolom dikendalikan dengan batas dua tahap
max_dynamic_types membatasi jumlah tipe dalam satu path key JSON yang disimpan sebagai file terpisah
max_dynamic_paths membatasi jumlah path key JSON yang disimpan sebagai subkolom terpisah
- Path JSON dinamis tambahan yang melewati batas
max_dynamic_paths disimpan sebagai shared data
- Contoh file:
C.object_shared_data.size0.bin, C.object_shared_data.paths.bin, C.object_shared_data.values.bin
object_shared_data.values bertipe String
- Setiap entri memiliki struktur
<binary_encoded_data_type><binary_value>
- Untuk shared data, statistik tambahan juga disimpan di
object_structure.bin
- Saat ini statistik nilai non-null disimpan untuk 10000 path pertama di antara path yang tersimpan dalam kolom shared data
Sintaks path JSON dan objek bersarang
- Tipe JSON dapat membaca nilai leaf dari setiap path sebagai subkolom berbasis nama path
- Nilai pada path yang tidak diberi type hint selalu bertipe Dynamic
- Contoh: tipe
C.a.d adalah Dynamic
- Subkolom subtipe dari tipe Dynamic dibaca dengan sintaks JSON khusus
- Objek JSON bersarang dapat dibaca seperti subkolom tipe JSON dengan sintaks
JSON_column.^some.path
- Saat ini sintaks dot tidak membaca objek bersarang karena alasan performa
- Untuk membaca nilai literal per path, struktur penyimpanan saat ini efisien
- Membaca seluruh sub-objek per path dapat menjadi lambat karena perlu membaca lebih banyak data
- Untuk mengembalikan objek, diperlukan sintaks
.^
- ClickHouse berencana menyatukan dua sintaks
. tersebut
Serialisasi discriminator compact
- Banyak path JSON dinamis mungkin sebagian besar memiliki tipe nilai yang sama
- Jika ada banyak path JSON yang unik tetapi sparse, file discriminator untuk setiap path sebagian besar akan berisi
255, yaitu nilai NULL
- File seperti ini terkompresi dengan baik, tetapi jika nilai semua baris sama, masih ada banyak duplikasi
- ClickHouse mengimplementasikan format compact untuk serialisasi discriminator
- Alih-alih menulis semua nilai discriminator
UInt8 seperti biasanya, jika semua discriminator pada granule target sama, hanya 3 nilai yang diserialisasi
- Penanda compact granule format
- Penanda jumlah nilai dalam granule tersebut
- Nilai discriminator
- Optimasi ini dikendalikan oleh pengaturan MergeTree
use_compact_variant_discriminators_serialization
- Nilai defaultnya aktif
- Dalam beberapa kasus, alih-alih menyimpan 8192 nilai berdasarkan index granularity umum, hanya 3 nilai yang disimpan
Status rilis dan langkah berikutnya
- Tipe JSON baru dirancang untuk menggantikan tipe Object('json') yang sudah deprecated
- Implementasinya tersedia sebagai fitur experimental untuk tujuan pengujian dalam rilis ClickHouse 24.08
- Roadmap JSON mencakup perbaikan untuk menggunakan path key JSON dalam primary key tabel atau data-skipping index
- Komponen seperti Variant dan Dynamic juga menjadi fondasi dukungan tipe semi-terstruktur tambahan seperti XML dan YAML di luar JSON
- Pengguna ClickHouse Cloud yang ingin menguji tipe data JSON baru harus menghubungi tim dukungan ClickHouse untuk meminta akses private preview
Belum ada komentar.