MaxCompute memungkinkan Anda mengonfigurasi properti shuffle dan sort untuk tabel guna mengaktifkan pengelompokan hash. Tabel yang dikelompokkan berdasarkan hash membantu mengoptimalkan rencana eksekusi, meningkatkan efisiensi operasi, dan menghemat sumber daya sesuai dengan karakteristik penyimpanan data. Topik ini menjelaskan cara menggunakan tabel yang dikelompokkan berdasarkan hash di MaxCompute.
Informasi latar belakang
id.SELECT t1.a, t2.b FROM t1 JOIN t2 ON t1.id = t2.id;MaxCompute menyediakan metode join berikut:- Broadcast Hash Join
Jika salah satu tabel yang akan digabungkan adalah tabel kecil, MaxCompute menggunakan metode broadcast hash join untuk menyiarkan tabel kecil ke semua instance tugas join, lalu melakukan hash join antara tabel kecil dan besar.
- Shuffle Hash Join
Jika kedua tabel yang akan digabungkan adalah tabel besar, data tidak dapat disiarkan. Dalam hal ini, hash shuffle dilakukan secara terpisah pada dua tabel berdasarkan kunci join. Hasil hash akan sama jika nilai kuncinya sama. Dengan cara ini, catatan dengan nilai kunci yang sama didistribusikan ke instance tugas join yang sama. Kemudian, setiap instance membuat tabel hash untuk catatan data dari tabel yang lebih kecil dan menggabungkan data dalam tabel hash dengan data dari tabel yang lebih besar secara berurutan berdasarkan kunci join.
- Sort Merge JoinJika kedua tabel yang akan digabungkan sangat besar, metode shuffle hash join tidak cocok karena sumber daya memori tidak cukup untuk membuat tabel hash. Dalam hal ini, hash shuffle dilakukan secara terpisah pada dua tabel berdasarkan kunci join. Kemudian, data diurutkan berdasarkan kunci join. Terakhir, catatan data yang diurutkan dari dua tabel digabungkan.
Gambar berikut menggambarkan proses sort merge join.
Dalam hal jumlah data di MaxCompute, metode sort merge join sering digunakan. Namun, metode ini mengonsumsi sejumlah besar sumber daya. Dalam gambar sebelumnya, operasi komputasi dilakukan saat data di-shuffle. Hasil perantara kemudian disimpan di disk. Saat reducer membaca data selama operasi berikutnya, pembacaan data dan pengurutan juga diperlukan. Dalam skenario dengan Mmapper danRreducer,M × Roperasi I/O terlibat. Gambar berikut menunjukkan rencana eksekusi fisik pekerjaan Fuxi. Dalam rencana eksekusi, dua tahap map dan satu tahap join diperlukan. Operasi dalam kotak merah adalah operasi shuffle dan sort.
Beberapa operasi join mungkin dilakukan berulang kali dalam kueri data. Sebagai contoh, Anda dapat mengubah pernyataan kueri asli menjadi pernyataan berikut:
Dalam pernyataan ini, kolom yang dipilih berbeda dari yang ada di pernyataan kueri asli, tetapi klausa JOIN-nya sama, dan seluruh proses shuffle dan sort-nya identik.SELECT t1.c, t2.d FROM t1 JOIN t2 ON t1.id = t2.id;Anda juga dapat mengubah pernyataan kueri asli menjadi pernyataan berikut:
Dalam pernyataan ini, tabel t1 dan t3 digabungkan. Namun, untuk tabel t1, seluruh proses shuffle dan sort tetap sama.SELECT t1.c, t3.d FROM t1 JOIN t3 ON t1.id = t3.id;Untuk mencegah operasi shuffle dan sort berulang, Anda dapat menyimpan data tabel di MaxCompute berdasarkan hash shuffle dan pengurutan data saat membuat tabel. Dengan cara ini, beberapa operasi tambahan dilakukan dalam proses pembuatan tabel, tetapi operasi shuffle dan join tidak dilakukan berulang kali selama kueri data. Gambar berikut menunjukkan rencana eksekusi fisik pekerjaan Fuxi yang menggabungkan tabel dengan karakteristik penyimpanan sebelumnya. Dalam rencana ini, operasi shuffle dan sort berulang tidak lagi dilakukan, dan tiga tahap diubah menjadi satu tahap.
Prosedur
Buat tabel yang dikelompokkan berdasarkan hash
- Sintaks
CREATE TABLE [IF NOT EXISTS] <table_name> [(<col_name> <data_type> [comment <col_comment>], ...)] [comment <table_comment>] [PARTITIONED BY (<col_name> <data_type> [comment <col_comment>], ...)] [CLUSTERED BY (<col_name> [, <col_name>, ...]) [SORTED BY (<col_name> [ASC | DESC] [, <col_name> [ASC | DESC] ...])] INTO <number_of_buckets> BUCKETS] [AS <select_statement>] - Contoh
- Tabel Non-partisi
CREATE TABLE T1 (a string, b string, c bigint) CLUSTERED BY (c) SORTED by (c) INTO 1024 BUCKETS; - Tabel Partisi
CREATE TABLE T1 (a string, b string, c bigint) PARTITIONED BY (dt string) CLUSTERED BY (c) SORTED by (c) INTO 1024 BUCKETS;
- Tabel Non-partisi
- Parameter
- CLUSTERED BY
Menentukan kunci hash berdasarkan mana MaxCompute melakukan operasi hash pada kolom tertentu. Setelah operasi hash dilakukan, MaxCompute mendistribusikan data ke bucket berdasarkan nilai hash. Untuk mencegah masalah skew data dan hot spot serta meningkatkan efisiensi eksekusi konkurensi, kami sarankan Anda menentukan kolom dengan rentang nilai besar dan jumlah nilai kunci duplikat yang kecil di CLUSTERED BY. Untuk mengoptimalkan operasi join, kami sarankan Anda memilih kunci join atau kunci agregat yang sering digunakan. Kunci join dan agregat mirip dengan kunci utama dalam database konvensional.
- SORTED BY
Menentukan cara mengurutkan bidang dalam bucket. Untuk meningkatkan kinerja kueri, kami sarankan Anda menjaga konfigurasi SORTED BY konsisten dengan parameter CLUSTERED BY. Jika Anda menentukan parameter SORTED BY, MaxCompute secara otomatis menghasilkan indeks dan mempercepat kueri berdasarkan indeks.
- INTO number_of_buckets BUCKETS
Menentukan jumlah bucket. Parameter ini wajib dan ditentukan berdasarkan jumlah data. Semakin banyak bucket menunjukkan konkurensi yang lebih tinggi dan efisiensi eksekusi pekerjaan yang lebih tinggi. Namun, jika terdapat jumlah bucket yang berlebihan, file kecil yang berlebihan mungkin dihasilkan. Konkurensi yang terlalu tinggi juga meningkatkan waktu CPU. Kami sarankan Anda menjaga ukuran data setiap bucket antara 500 MB hingga 1 GB. Jika sebuah tabel sangat besar, Anda dapat meningkatkan ukuran data setiap bucket secara tepat. Dalam skenario optimasi join, langkah shuffle dan sort harus dihapus dari operasi join pada dua tabel. Oleh karena itu, jumlah bucket dalam sebuah tabel harus merupakan kelipatan dari jumlah bucket di tabel lainnya. Sebagai contoh, satu tabel memiliki
256bucket dan tabel lainnya memiliki512bucket. Kami sarankan Anda menetapkan jumlah bucket menjadi 2 pangkat N, seperti 512, 1.024, 2.048, atau 4.096. Dengan cara ini, MaxCompute dapat secara otomatis membagi dan menggabungkan bucket, dan langkah shuffle dan sort dapat dihapus.
- CLUSTERED BY
Ubah properti pengelompokan hash tabel
- Sintaks
-- Ubah tabel menjadi tabel yang dikelompokkan berdasarkan hash. ALTER TABLE <table_name> [CLUSTERED BY (<col_name> [, <col_name>, ...]) [SORTED BY (<col_name> [ASC | DESC] [, <col_name> [ASC | DESC] ...])] INTO <number_of_buckets> BUCKETS]; -- Ubah tabel yang dikelompokkan berdasarkan hash menjadi tabel non-hash-clustered. ALTER TABLE <table_name> NOT CLUSTERED; - Catatan Penggunaan
- Pernyataan ALTER TABLE hanya dapat memodifikasi properti klustering tabel partisi. Properti klustering tidak dapat dimodifikasi setelah ditambahkan ke tabel non-partisi.
- Pernyataan ALTER TABLE hanya berlaku untuk partisi baru tabel, yang mencakup partisi baru yang dihasilkan dengan menggunakan pernyataan INSERT OVERWRITE. Partisi baru disimpan berdasarkan properti pengelompokan hash. Format penyimpanan partisi yang ada tetap tidak berubah.
- Pernyataan ALTER TABLE hanya berlaku untuk partisi baru tabel. Oleh karena itu, Anda tidak dapat menentukan partisi dalam pernyataan ini.
Verifikasi eksplisit properti tabel
Extended Info dari hasil yang dikembalikan.DESC EXTENDED <table_name>;Gambar berikut menunjukkan contoh hasil yang dikembalikan.
Untuk tabel partisi, Anda juga harus mengeksekusi pernyataan berikut untuk melihat properti partisi dalam tabel.DESC EXTENDED <table_name> partition(<pt_spec>);Gambar berikut menunjukkan contoh hasil yang dikembalikan.
Keuntungan pengelompokan hash
Pemangkasan bucket dan optimasi indeks
CREATE TABLE t1 (id bigint,
a string,
b string)
CLUSTERED BY (id)
SORTED BY (id) into 1000 BUCKETS;
...
SELECT t1.a, t1.b FROM t1 WHERE t1.id=12345;Untuk tabel biasa, operasi kueri memerlukan operasi pemindaian tabel penuh. Jika jumlah data dalam tabel terlalu besar, sejumlah besar sumber daya mungkin dikonsumsi. Dalam pernyataan CREATE TABLE sebelumnya, data di-hash shuffle dan diurutkan berdasarkan kolom id. Dengan cara ini, operasi kueri sangat disederhanakan.- Pekerjaan kueri dapat menemukan bucket yang sesuai dengan nilai
12345. Dengan cara ini, pekerjaan hanya perlu memindai data di satu bucket saja, bukan semua 1.000 bucket. Proses ini disebut pemangkasan bucket. - Data dalam bucket diurutkan dan disimpan berdasarkan kolom
id. MaxCompute secara otomatis membuat indeks dan menggunakan fungsi INDEX LOOKUP untuk menemukan catatan yang relevan.
Sebagai contoh, untuk tugas data besar, total 1.111 mapper digunakan untuk membaca 42,7 miliar catatan, dan 26 catatan cocok dalam hasil akhir. Seluruh proses memakan waktu 1 menit dan 48 detik. Untuk data yang sama dan kueri yang sama, jika Anda menggunakan tabel yang dikelompokkan berdasarkan hash, Anda dapat langsung menemukan satu bucket dan menggunakan indeks untuk membaca data dari halaman tertentu. Dengan cara ini, empat mapper digunakan untuk membaca 10.000 catatan. Seluruh proses hanya memakan waktu 6 detik.
Optimasi agregat
SELECT department, SUM(salary) FROM employee GROUP BY (department);Dalam kebanyakan kasus, jika Anda menanyakan data di kolom department dari tabel, data di kolom department di-shuffle dan diurutkan. Kemudian, operasi stream aggregate dilakukan untuk mengelompokkan data berdasarkan department. Namun, jika CLUSTERED BY (department) dan SORTED BY (department) ditentukan dalam pernyataan saat Anda membuat tabel, operasi shuffle dan sort tidak lagi diperlukan untuk operasi kueri.Optimasi penyimpanan
Selain optimasi komputasi, ruang penyimpanan sangat dihemat jika tabel di-shuffle dan disimpan secara terurut. MaxCompute menggunakan penyimpanan kolom di lapisan bawah. Catatan yang memiliki nilai kunci yang sama atau serupa disimpan bersama oleh fungsi sort, yang memfasilitasi pengkodean dan kompresi. Dengan cara ini, efisiensi kompresi secara signifikan meningkat. Dalam beberapa kasus pengujian ekstrem, tabel yang datanya diurutkan dapat menghemat 50% ruang penyimpanan dibandingkan dengan tabel yang datanya tidak diurutkan. Jika tabel memiliki siklus hidup yang panjang, kami sarankan Anda mengonfigurasi tabel sebagai tabel yang dikelompokkan berdasarkan hash.
lineitem dengan 100 GB data dalam dataset TPC-H digunakan. Tabel tersebut berisi data dari berbagai tipe data seperti INT, DOUBLE, dan STRING. Jika data yang sama dan metode kompresi yang sama digunakan, tabel yang dikelompokkan berdasarkan hash dapat menghemat sekitar 10% ruang penyimpanan. Gambar-gambar berikut menunjukkan hasil perbandingan.- Pengelompokan hash tidak digunakan.

- Pengelompokan hash digunakan.

Data uji dan analisis
Bagian ini menjelaskan pengujian pada dataset TPC-H standar untuk mengukur peningkatan kinerja keseluruhan yang diperkenalkan oleh pengelompokan hash. Dalam pengujian, data sebesar 1 TB disimpan dalam 500 bucket. Kecuali untuk tabel nation dan region di mana sejumlah kecil data disimpan, kolom pertama di tabel lainnya digunakan sebagai kunci kluster dan kunci sort. Hasil pengujian keseluruhan menunjukkan bahwa total waktu CPU berkurang sekitar 17,3% dan total durasi eksekusi pekerjaan berkurang sekitar 12,8% setelah tabel dikelompokkan berdasarkan hash.
Properti klustering tidak dapat digunakan untuk beberapa operasi kueri pada dataset TPC-H, terutama untuk dua operasi kueri yang paling memakan waktu. Oleh karena itu, peningkatan efisiensi total tidak sepenuhnya jelas. Untuk operasi kueri yang menggunakan properti klustering, peningkatan efisiensi sepenuhnya jelas. Sebagai contoh, efisiensi kueri meningkat sekitar 68% untuk TPC-H Q4, sekitar 62% untuk TPC-H Q12, dan sekitar 47% untuk TPC-H Q10.
Gambar berikut menunjukkan rencana eksekusi pekerjaan Fuxi setelah pengelompokan hash diaktifkan untuk tabel. Dalam rencana eksekusi, grafik asiklik terarah (DAG) secara signifikan disederhanakan, yang merupakan kunci untuk peningkatan kinerja.