Klausa GROUP BY atau ORDER BY yang redundan dalam kueri SQL menyebabkan database melakukan operasi pengurutan atau penghashan yang tidak perlu. Operasi ini mengonsumsi sumber daya CPU dan memori secara signifikan serta berdampak buruk terhadap performa kueri pemrosesan analitis (AP), terutama saat menangani dataset besar. Fitur penghapusan GROUP BY/ORDER BY pada PolarDB for MySQL secara otomatis mendeteksi dan menghapus operasi redundan tersebut berdasarkan ketergantungan fungsional (functional dependency). Fitur ini dapat memberikan peningkatan performa signifikan hingga 29% dalam pengujian benchmark TPC-H, serta mengurangi konsumsi sumber daya untuk kueri analitis tanpa memerlukan perubahan apa pun pada kode aplikasi Anda.
Cakupan
Seri produk: Cluster Edition, Standard Edition.
Versi: MySQL 8.0.2, revisi 8.0.2.2.33 atau yang lebih baru.
Aktifkan fitur penghapusan
Anda dapat mengontrol perilaku fitur optimasi ini dengan mengatur parameter loose_groupby_elimination_mode dan loose_orderby_elimination_mode.
Metode modifikasi parameter kluster PolarDB berbeda antara Konsol dan sesi database. Perbedaannya adalah sebagai berikut:
Kompatibilitas: Untuk menjaga kompatibilitas dengan file konfigurasi MySQL, beberapa parameter kluster di Konsol PolarDB menggunakan awalan loose_.
Prosedur: Temukan dan ubah parameter yang memiliki awalan
loose_.
Di sesi database (menggunakan command line atau client)
Prosedur: Saat Anda menggunakan perintah
SETuntuk mengubah parameter dalam sesi database, hapus awalanloose_dan gunakan nama parameter aslinya.
Nama Parameter | Tingkat | Deskripsi |
| Global/Sesi | Mengontrol fitur penghapusan
|
| Mengontrol fitur penghapusan
|
Cara kerja
Fitur penghapusan GROUP BY/ORDER BY menggunakan ketergantungan fungsional (FD). Memahami cara kerja fitur ini dapat membantu Anda menulis SQL yang lebih baik dan memprediksi apakah suatu optimasi akan diterapkan.
Apa itu ketergantungan fungsional? Jika nilai kolom A (atau sekumpulan kolom) secara unik menentukan nilai kolom B, maka B bergantung secara fungsional pada A. Hubungan ini ditulis sebagai
A -> B. Misalnya, pada tabel pengguna, primary keyuser_idsecara unik menentukannickname. Oleh karena itu, ketergantungan fungsionaluser_id -> nicknameada.Bagaimana pengoptimal menemukan ketergantungan fungsional: Pengoptimal PolarDB secara otomatis melakukan inferensi ketergantungan dari metadata dan kondisi kueri berikut:
Primary key dan unique key:
PRIMARY KEYatauUNIQUE KEYyang didefinisikan dalam skema tabel merupakan sumber paling langsung dari ketergantungan fungsional.Kondisi equi-join: Keunikan primary key dapat dipropagasi ke tabel terkait melalui kondisi equi-join, seperti
t1.pk = t2.fkdalam klausaJOIN.Kondisi filter konstan: Filter kesetaraan dalam klausa
WHERE, sepertiWHERE status = 'active', menjadikan kolom tersebut konstan dalam set hasil.
Aturan optimasi inti:
Penghapusan `GROUP BY`:
Jika kolom-kolom dalam klausa
GROUP BYsudah secara unik mengidentifikasi setiap baris dalam set hasil—misalnya dengan menyertakan primary key tabel—maka seluruh operatorGROUP BYbersifat redundan dan dapat dihapus dengan aman.Jika semua kolom dalam klausa
GROUP BYbersifat konstan, seluruh operatorGROUP BYdapat dihapus dan diganti denganLIMIT 1.
Penghapusan `ORDER BY`: Jika semua kolom dalam klausa
ORDER BYbersifat konstan, seluruh operatorORDER BYbersifat redundan dan dapat dihapus dengan aman.Penyederhanaan `GROUP BY`/`ORDER BY`: Jika terdapat ketergantungan fungsional antar kolom dalam klausa
GROUP BYatauORDER BY, sepertiGROUP BY x, ydi manax -> ydiketahui, klausa tersebut dapat disederhanakan menjadiGROUP BY x. Hal ini mengurangi jumlah kolom yang digunakan untuk pengelompokan atau pengurutan.
Skenario optimasi khas dan contoh
Skenario 1: Pengelompokan berdasarkan primary key atau unique key
Saat klausa GROUP BY mencakup primary key atau unique key tabel, pengelompokan berdasarkan kolom lain bersifat redundan karena key tersebut sudah mengidentifikasi baris secara unik.
Skenario bisnis: Hitung total jumlah pesanan untuk setiap pengguna dan tampilkan username-nya.
SQL asli:
-- user_id adalah primary key tabel user dan secara unik menentukan user_name. SELECT u.user_id, u.user_name, COUNT(o.order_id) FROM user u JOIN orders o ON u.user_id = o.user_id GROUP BY u.user_id, u.user_name;Analisis optimasi: Karena
user_idadalah primary key, nilai tersebut secara unik menentukanuser_name. Pengoptimal mendeteksi FDuser_id -> user_namedan secara otomatis menyederhanakanGROUP BY u.user_id, u.user_namemenjadiGROUP BY u.user_id. Hal ini menghilangkan operasi pengelompokan yang tidak perlu padauser_name.
Skenario 2: Pengelompokan berdasarkan konstanta
Saat semua kolom dalam klausa GROUP BY bersifat konstan, seluruh operasi pengelompokan bersifat redundan karena set hasil berisi paling banyak satu baris.
Skenario bisnis: Kueri informasi status tertentu untuk pengguna tertentu. Ini merupakan pola SQL yang jarang digunakan, tetapi pengoptimal dapat menanganinya.
SQL asli:
SELECT a, b FROM t1 WHERE a = 1 AND b = 1 GROUP BY a, b;Analisis optimasi: Pengoptimal mendeteksi bahwa kolom
GROUP BYadanbditentukan sebagai konstanta dalam klausaWHERE. Pengoptimal menghapus operatorGROUP BYdan menambahkanLIMIT 1.SELECT a, b FROM t1 WHERE a = 1 AND b = 1 LIMIT 1;
Skenario 3: Pengelompokan kompleks dalam join multi-tabel (TPC-H Q10)
Dalam kueri kompleks dengan JOIN multi-tabel, ketergantungan fungsional dapat dipropagasi melalui kondisi join. Pengoptimal memanfaatkan propagasi ini untuk menghilangkan pengelompokan redundan yang lebih kompleks.
SQL asli (TPC-H Q10):
SELECT c_custkey, c_name, c_acctbal, c_phone, n_name, c_address, c_comment, SUM(l_extendedprice * (1 - l_discount)) AS revenue FROM customer, orders, lineitem, nation WHERE c_custkey = o_custkey AND l_orderkey = o_orderkey AND c_nationkey = n_nationkey -- Other filter conditions... GROUP BY c_custkey, c_name, c_acctbal, c_phone, n_name, c_address, c_comment ORDER BY revenue DESC LIMIT 20;Analisis optimasi:
Ketergantungan primary key: Pada tabel
customer,c_custkeyadalah primary key. Oleh karena itu, nilai tersebut secara unik menentukan semua kolom lainnya, sepertic_name, c_acctbal, c_phone, c_address, c_comment, dan c_nationkey.Propagasi ketergantungan: Kondisi
JOINadalahc_nationkey = n_nationkey. Karenan_nationkeyadalah primary key tabelnationdan menentukann_name, pengoptimal dapat menyimpulkan bahwac_custkeyjuga secara unik menentukann_name.Penyederhanaan akhir: Secara ringkas, semua kolom dalam klausa
GROUP BY, sepertic_namedanc_acctbal, bergantung secara fungsional padac_custkey. Oleh karena itu, pengoptimal menyederhanakan daftarGROUP BYyang kompleks menjadiGROUP BY c_custkey. Hal ini sangat mengurangi kompleksitas perhitungan pengelompokan.
SELECT c_custkey, c_name, c_acctbal, c_phone, n_name, c_address, c_comment, SUM(l_extendedprice * (1 - l_discount)) AS revenue FROM customer, orders, lineitem, nation WHERE c_custkey = o_custkey AND l_orderkey = o_orderkey AND c_nationkey = n_nationkey -- Other filter conditions... GROUP BY c_custkey ORDER BY revenue DESC LIMIT 20;
Skenario 4: Skenario ORDER BY
Saat terdapat ketergantungan fungsional antar kolom dalam klausa ORDER BY, pengoptimal dapat menyederhanakan operasi pengurutan dengan mengurangi jumlah kolom yang diurutkan.
Skenario bisnis: Urutkan tabel di mana beberapa kolom ditentukan secara unik oleh kolom lainnya.
Skema tabel:
CREATE TABLE t1 ( a int, b int, c int as (a + b) unique not null );SQL asli:
EXPLAIN SELECT a, b FROM t1 ORDER BY a,b,c;Analisis optimasi: Karena kolom
cdihitung dari kolomadanb(c = a + b) dan didefinisikan sebagaiunique not null, terdapat ketergantungan fungsional:(a, b) -> c. Pengoptimal mengenali ketergantungan ini dan secara otomatis menyederhanakanORDER BY a, b, cmenjadiORDER BY a, b, sehingga mengurangi kompleksitas operasi pengurutan.SHOW warnings; +-------+------+-------------------------------------------------------------------------------------------------------------------------------+ | Level | Code | Message | +-------+------+-------------------------------------------------------------------------------------------------------------------------------+ | Note | 1003 | /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` order by `test`.`t1`.`a`,`test`.`t1`.`b` | +-------+------+-------------------------------------------------------------------------------------------------------------------------------+
Pengujian Performa
Pengujian pada dataset standar TPC-H 100 GB menunjukkan bahwa mengaktifkan fitur penghapusan GROUP BY secara signifikan meningkatkan performa kueri Q10.
Implementasi TPC-H dalam topik ini didasarkan pada pengujian benchmark TPC-H dan tidak dapat dibandingkan dengan hasil benchmark TPC-H yang dipublikasikan. Pengujian yang dijelaskan dalam topik ini tidak sepenuhnya memenuhi semua persyaratan TPC-H.
Data berikut berasal dari pengujian dalam skenario tertentu. Peningkatan performa aktual dapat bervariasi tergantung pada faktor-faktor seperti kompleksitas kueri, distribusi data, dan spesifikasi kluster.
Skenario Pengujian | Mengaktifkan | Dinonaktifkan (waktu eksekusi) | Peningkatan Performa |
Menggunakan In-Memory Column Index (IMCI) pada 1 DOP (dalam 1 hari setelah pembuatan data) | 48 detik | 68 detik | 29% |
Menggunakan In-Memory Column Index (IMCI) pada 32 DOP (dalam 32 hari setelah pembuatan data) | 1,9 detik | 2,6 detik | 27% |