Topik ini menjelaskan cara memilih kunci partisi tabel yang tepat di ApsaraDB for ClickHouse untuk mengoptimalkan kinerja dan meningkatkan efisiensi manajemen data dalam skenario desain tabel.
Kunci partisi
Fitur partisi mengatur data ke dalam segmen logis berdasarkan kunci yang ditentukan. Data dibagi menjadi fragmen terpisah (parts) sesuai dengan kunci partisi.
Di ApsaraDB for ClickHouse Enterprise Edition, ketika Anda mengeksekusi pernyataan INSERT untuk memasukkan beberapa baris ke dalam tabel yang tidak menggunakan kunci partisi, semua data ditulis ke bagian data baru. Namun, ketika sebuah tabel menggunakan kunci partisi, sistem melakukan operasi berikut:
Memeriksa nilai kunci partisi dari baris yang dimasukkan.
Membuat bagian data di penyimpanan untuk setiap nilai kunci partisi unik.
Menetapkan baris ke bagian data yang sesuai berdasarkan nilai kunci partisi.
Tabel tanpa kunci partisi
| Tabel dengan kunci partisi
|
Prinsip inti
Untuk mengurangi jumlah permintaan tulis yang dikirim ke bucket Object Storage Service tempat menyimpan data untuk ApsaraDB for ClickHouse Enterprise Edition, kunci partisi harus memprioritaskan kardinalitas rendah (jumlah kecil nilai partisi berbeda) dan bidang yang mudah dikelola (seperti waktu). Kunci primer harus mencakup bidang yang umumnya difilter dan berada dalam urutan logis. Hindari bidang kardinalitas tinggi, partisi yang terlalu rinci, dan kunci primer yang tidak relevan agar dapat memanfaatkan keunggulan kinerja tinggi dan kemudahan pengelolaan ClickHouse.
Partisi adalah alat manajemen data
Partisi terutama digunakan untuk kedaluwarsa data yang efisien, penyimpanan bertingkat, penghapusan batch, dan tugas manajemen lainnya, bukan sebagai alat utama optimasi kueri. Untuk informasi selengkapnya, lihat Memilih Kunci Partisi.
Pilih bidang kardinalitas rendah sebagai kunci partisi
Kami merekomendasikan agar jumlah partisi berada di antara 100 hingga 1.000. Hindari menggunakan bidang kardinalitas tinggi (bidang dengan banyak nilai berbeda, seperti user_id atau nomor perangkat) sebagai kunci partisi. Jika tidak, jumlah bagian dapat meningkat secara eksponensial, memengaruhi kinerja atau bahkan menyebabkan kesalahan "too many parts".
Metode partisi umum adalah partisi berbasis waktu
Buat partisi berdasarkan dimensi waktu seperti bulan atau hari, menggunakan fungsi seperti toYYYYMM(date), toStartOfMonth(date), atau toDate(date). Hal ini memfasilitasi manajemen siklus hidup data dan penyimpanan bertingkat data panas dan dingin. Untuk informasi selengkapnya, lihat Kunci Partisi Kustom.
Kunci partisi harus selaras erat dengan persyaratan manajemen seperti siklus hidup data, pengarsipan, pembersihan, dan lainnya
Beri prioritas pada dimensi yang mudah dikelola secara batch dari perspektif bisnis. Untuk informasi selengkapnya, lihat Aplikasi partisi.
Rekomendasi desain tabel
Prioritaskan partisi berbasis waktu
Untuk skenario log, deret waktu, dan pemantauan, kami merekomendasikan membuat partisi berdasarkan bulan atau hari. Misalnya, membuat partisi tabel log berdasarkan bulan, dengan data setiap bulan berada di partisi terpisah, memberikan keuntungan berikut:
Manajemen data yang efisien: Anda dapat menghapus, mengarsipkan, atau memindahkan data secara batch berdasarkan partisi. Misalnya, dalam skenario tiket khas di mana
ALTER TABLE DELETEdigunakan untuk menghapus data kedaluwarsa, dengan partisi bulanan atau harian, Anda hanya perlu menggunakanDROP PARTITIONuntuk menghapus partisi yang sesuai tanpa memindai seluruh tabel, sehingga sangat meningkatkan efisiensi.Penerapan mudah manajemen siklus hidup data (TTL): Dikombinasikan dengan kebijakan TTL, partisi kedaluwarsa dapat dibersihkan secara otomatis, menyederhanakan operasi dan pemeliharaan.
Pemangkasan partisi meningkatkan efisiensi kueri: Saat memfilter berdasarkan waktu dalam kueri, ClickHouse hanya perlu memindai partisi yang relevan, melewatkan yang tidak relevan, sehingga secara signifikan mengurangi I/O dan mempercepat kecepatan kueri.
Hindari bidang kardinalitas tinggi untuk partisi
Misalnya ID pengguna, nomor pesanan, atau nomor perangkat. Sebagai contoh, jika sebuah tabel menggunakan user_id sebagai kunci partisi, yang merupakan bidang kardinalitas tinggi (setiap pengguna direpresentasikan secara unik, menunjukkan kardinalitas tinggi), hal ini akan menghasilkan jumlah partisi yang sangat besar dengan kekurangan berikut:
Eksplosi partisi: Setiap ID pengguna unik menghasilkan satu partisi, mengakibatkan jumlah partisi yang sangat besar jauh melampaui rentang yang direkomendasikan yaitu 100–1.000, menyebabkan tekanan besar pada manajemen metadata dan sistem file.
Kegagalan penggabungan latar belakang: ClickHouse hanya menggabungkan bagian dalam partisi yang sama. Terlalu banyak partisi mencegah operasi penggabungan, menghasilkan banyak bagian kecil yang memengaruhi kinerja kueri dan penulisan.
Penurunan kinerja kueri: Terlalu banyak partisi memerlukan pemindaian metadata partisi dalam jumlah besar selama kueri, mengurangi efisiensi kueri.
Kelelahan sumber daya instance: Terlalu banyak bagian partisi mengonsumsi memori dan handle file dalam jumlah besar, berpotensi menyebabkan ClickHouse lambat memulai atau gagal.
Hindari partisi yang terlalu rinci
Misalnya partisi berdasarkan jam, menit, atau detik, kecuali volume data sangat besar dan ada persyaratan khusus. Sebagai contoh, jika sebuah tabel menggunakan toYYYYMMDDhhmm(event_time) untuk membuat partisi per menit, hal ini akan menghasilkan 1.440 partisi per hari dan lebih dari 500.000 partisi per tahun, dengan kekurangan berikut:
Terlalu banyak partisi: Partisi yang terlalu rinci menghasilkan jumlah partisi yang jauh melampaui rentang yang direkomendasikan yaitu 100–1.000, sangat meningkatkan beban pada manajemen metadata dan sistem file.
Kesalahan khas:
DB::Exception: Too many parts (N). Merges are processing significantly slower than inserts.Kegagalan penggabungan latar belakang: ClickHouse hanya menggabungkan bagian dalam partisi yang sama. Terlalu banyak partisi mencegah operasi penggabungan, menghasilkan banyak bagian kecil yang memengaruhi kinerja kueri dan penulisan.
Penurunan kinerja kueri dan penulisan: Terlalu banyak partisi memerlukan pemindaian metadata partisi dalam jumlah besar selama kueri, mengurangi efisiensi kueri, sekaligus memperlambat penulisan karena jumlah bagian yang berlebihan.
Kunci partisi harus berupa bidang asli atau ekspresi sederhana
Hindari fungsi kompleks agar ClickHouse dapat memanfaatkan pemangkasan partisi.
Rancang kunci partisi bersamaan dengan kunci primer
Kunci primer harus mencakup bidang filter yang umumnya dikueri, sedangkan kunci partisi berfungsi untuk tujuan manajemen data.
Sebagai contoh, untuk tabel log di mana kebutuhan bisnis khas adalah sering mengkueri berdasarkan rentang waktu dan nama layanan sekaligus membersihkan data kedaluwarsa secara berkala, desainnya adalah:
Kunci partisi: toYYYYMM(event_time), satu partisi per bulan, memfasilitasi penghapusan batch bulanan, pengarsipan, penyimpanan bertingkat data panas dan dingin, serta operasi manajemen data lainnya.
Kunci primer: (service_name, event_time), untuk kueri umum seperti
WHERE service_name = 'A' AND event_time BETWEEN ..., yang dapat sepenuhnya memanfaatkan indeks kunci primer untuk pemangkasan data guna mempercepat kueri.
Contoh desain tabel
CREATE TABLE logs
(
event_time DateTime,
service_name String,
log_level String,
message String
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(event_time) -- Partisi berdasarkan bulan untuk memudahkan manajemen data
ORDER BY (service_name, event_time) -- Kunci primer mencakup bidang yang umumnya difilterPilihan kunci partisi yang tidak disarankan
Kunci partisi sebagai user_id (kardinalitas tinggi): Satu partisi per pengguna, menghasilkan terlalu banyak partisi, kegagalan penggabungan, dan kinerja yang sangat buruk.
Kunci partisi sebagai device_id (kardinalitas tinggi): Seperti di atas, menyebabkan kesalahan "too many parts" dan partisi yang tidak dapat dikelola.
Kunci partisi sebagai order_id (kardinalitas tinggi): Satu partisi per pesanan, fragmentasi ekstrem.
Kunci partisi sebagai name (string kardinalitas tinggi): Jumlah partisi tidak terkendali, sulit dikelola.
Kunci partisi sebagai toHour(event_time) (terlalu rinci): 24 partisi per hari, jumlah partisi sangat besar seiring waktu, kegagalan penggabungan.
Kunci partisi sebagai toMinute(event_time) (sangat rinci): Eksplosi partisi, sangat memengaruhi kinerja.
Kunci primer sebagai bidang kardinalitas tinggi dengan urutan tidak logis: Misalnya, ORDER BY (user_id, event_time), tetapi kueri umumnya berdasarkan event_time, mengakibatkan pemanfaatan indeks kunci primer yang rendah.
Kunci primer dengan terlalu banyak bidang: Misalnya, ORDER BY (a, b, c, d, e, f, g, h, i, j), menghasilkan ukuran indeks kunci primer yang besar dan konsumsi memori tinggi.
Kunci primer sebagai bidang kardinalitas rendah: Misalnya, ORDER BY (status), hanya memiliki beberapa nilai status, mengakibatkan kemampuan pemangkasan indeks kunci primer yang sangat buruk.
Kunci partisi dan kunci primer sama sekali tidak terkait, dan keduanya tidak mencakup kondisi kueri umum: Misalnya, kunci partisi adalah region, kunci primer adalah type, tetapi kueri umumnya berdasarkan event_time, sehingga baik partisi maupun kunci primer tidak mempercepat kueri.

