GroupJoin adalah operator kueri di PolarDB for MySQL yang menggabungkan HASH JOIN dan HASH GROUP BY dalam satu kali pemindaian data. Dengan menghilangkan tabel hash kedua yang diperlukan oleh eksekusi sekuensial, GroupJoin mengurangi ukuran hasil antara dan meningkatkan performa kueri analitis pada operasi yang diaktifkan oleh In-Memory Column Index (IMCI).
Sebelum membaca topik ini, pastikan Anda memahami HASH JOIN dan HASH GROUP BY.
Kapan GroupJoin berlaku
GroupJoin berlaku jika semua kondisi berikut terpenuhi:
Kueri melakukan EQUAL JOIN dan GROUP BY.
Kunci GROUP BY sesuai dengan kunci gabungan di salah satu sisi JOIN (atau secara fungsional bergantung padanya).
Setiap fungsi agregat hanya mereferensi satu sisi JOIN — bukan keduanya. Misalnya,
SUM(t1.a + t2.a)tidak didukung.
Pada operasi PolarDB for MySQL yang diaktifkan IMCI, GroupJoin secara konsisten memberikan performa lebih baik dibandingkan kombinasi sekuensial HASH JOIN + HASH GROUP BY, kecuali dalam satu kasus: RIGHT OUTER JOIN dikombinasikan dengan GROUP BY pada sisi kanan.
Latar belakang
Pertimbangkan kueri berikut:
SELECT
key1,
SUM(sales) AS total_sales
FROM
fact_table LEFT JOIN dimension_table ON fact_table.key1 = dimension_table.key1
GROUP BY
fact_table.key1
ORDER BY
total_sales
LIMIT 100;Tanpa GroupJoin, kueri ini memerlukan dua operasi terpisah:
HASH JOIN — membangun tabel hash dari
dimension_table.key1, lalu melakukan probing menggunakanfact_table.key1.HASH GROUP BY — membangun tabel hash kedua dari
fact_table.key1untuk mengagregasi hasil.
Kedua operasi menggunakan key1 untuk membangun tabel hash, yang bersifat redundan. Untuk tabel fakta berisi M baris dan tabel dimensi berisi N baris di mana key1 adalah kunci unik, HASH JOIN menghasilkan M baris dan HASH GROUP BY kemudian membangun tabel hash lain berisi M baris.
GroupJoin menghilangkan tabel hash kedua dengan menggabungkan penggabungan dan agregasi dalam satu kali pemindaian: ia membangun tabel hash berisi N baris dari tabel dimensi dan langsung melakukan agregasi ke dalamnya, sehingga mengurangi konsumsi memori dan jumlah baris antara.
Cara kerja
GroupJoin dieksekusi dalam dua fase:
Fase build — tabel sisi kiri yang lebih kecil membangun tabel hash. Fungsi agregat dijalankan pada data sisi kiri selama fase ini (setara dengan
HashGroupBy left_table).Fase probe — tabel sisi kanan yang lebih besar melakukan probing terhadap tabel hash. Baris yang cocok diagregasikan ke dalam entri tabel hash yang sudah ada. Baris yang tidak cocok diabaikan.
Batasan
Kunci GROUP BY harus sesuai dengan kunci gabungan di salah satu sisi. Dalam beberapa kasus, ketergantungan fungsional terhadap bagian dari kunci gabungan sudah cukup.
Untuk RIGHT OUTER JOIN dikombinasikan dengan GROUP BY pada sisi kanan, kunci gabungan sisi kanan harus unik. Jika keunikan tidak dapat dijamin, ubah JOIN menjadi LEFT OUTER JOIN atau lakukan GROUP BY pada sisi kiri. Jika keduanya tidak memungkinkan, GroupJoin tidak dapat digunakan.
Setiap fungsi agregat hanya boleh mereferensi satu tabel dalam satu waktu. GroupJoin tidak berlaku jika fungsi agregat mencakup kedua tabel, seperti
SUM(t1.a + t2.a).
Perilaku berdasarkan jenis JOIN
INNER JOIN, GROUP BY sisi kiri
l_table INNER JOIN r_table
ON l_table.key1 = r_table.key1
GROUP BY l_table.key1Deskripsi berikut mengasumsikan pernyataan SQL dieksekusi sesuai urutan yang ditunjukkan, dan objek join tidak dialihkan secara dinamis.
Membangun tabel hash dari tabel kiri, menjalankan fungsi agregat pada data sisi kiri. Penghitung ulang melacak berapa banyak baris sisi kanan yang cocok dengan setiap entri tabel hash.
Menjalankan probing terhadap tabel hash menggunakan tabel kanan. Untuk setiap baris sisi kanan yang cocok, tambahkan penghitung ulang sebesar 1 dan jalankan fungsi agregat pada data sisi kanan. Buang baris yang tidak cocok.
Setelah penggabungan, keluarkan hanya entri tabel hash yang cocok. Buang entri yang tidak cocok.
Hasil agregasi akhir sama dengan
SUM(expr) × repeat count. Misalnya, jikaSUM(expr)bernilai 200 dan penghitung ulang bernilai 5, hasilnya adalah 1.000.
INNER JOIN, GROUP BY sisi kanan
l_table INNER JOIN r_table
ON l_table.key1 = r_table.key1
GROUP BY r_table.key1Karena l_table.key1 sama dengan r_table.key1 dalam INNER JOIN, skenario ini setara dengan INNER JOIN dengan GROUP BY pada sisi kiri.
LEFT OUTER JOIN, GROUP BY sisi kiri
l_table LEFT OUTER JOIN r_table
ON l_table.key1 = r_table.key1
GROUP BY l_table.key1Membangun tabel hash dari tabel kiri dan menjalankan fungsi agregat pada data sisi kiri. Gunakan penghitung ulang untuk agregasi sisi kanan.
Menjalankan probing terhadap tabel hash menggunakan tabel kanan. Entri yang cocok menambah penghitung ulang dan menjalankan fungsi agregat sisi kanan. Baris sisi kanan yang tidak cocok dibuang.
Setelah penggabungan, keluarkan entri yang cocok. Kumpulkan entri tabel hash yang tidak cocok ke dalam kelompok terpisah dengan input NULL untuk semua fungsi agregat sisi kanan.
LEFT OUTER JOIN, GROUP BY sisi kanan
l_table LEFT OUTER JOIN r_table
ON l_table.key1 = r_table.key1
GROUP BY r_table.key1Membangun tabel hash dari tabel kiri dan menjalankan fungsi agregat pada data sisi kiri. Gunakan penghitung ulang untuk agregasi sisi kanan.
Menjalankan probing terhadap tabel hash menggunakan tabel kanan. Entri yang cocok menambah penghitung ulang dan menjalankan fungsi agregat sisi kanan. Baris sisi kanan yang tidak cocok dibuang.
Setelah penggabungan, keluarkan entri yang cocok. Kumpulkan entri yang tidak cocok ke dalam kelompok terpisah dengan input NULL untuk semua fungsi agregat sisi kanan.
RIGHT OUTER JOIN, GROUP BY sisi kiri
l_table RIGHT OUTER JOIN r_table
ON l_table.key1 = r_table.key1
GROUP BY l_table.key1Membangun tabel hash dari tabel kiri dan menjalankan fungsi agregat pada data sisi kiri. Gunakan penghitung ulang untuk agregasi sisi kanan.
Menjalankan probing terhadap tabel hash menggunakan tabel kanan. Untuk entri yang cocok, tambahkan penghitung ulang dan jalankan fungsi agregat sisi kanan. Kumpulkan semua baris sisi kanan yang tidak cocok ke dalam kelompok terpisah dengan hasil NULL untuk fungsi agregat sisi kiri.
Setelah penggabungan, keluarkan entri tabel hash yang cocok. Buang entri yang tidak cocok.
RIGHT OUTER JOIN, GROUP BY sisi kanan
l_table RIGHT OUTER JOIN r_table
ON l_table.key1 = r_table.key1
GROUP BY r_table.key1r_table.key1 harus unik. Jika keunikan tidak dapat dijamin, gunakan pengoptimal untuk mengubah JOIN menjadi LEFT OUTER JOIN atau ubah GROUP BY ke sisi kiri.Membangun tabel hash dari tabel kiri dan menjalankan fungsi agregat pada data sisi kiri. Gunakan penghitung ulang untuk agregasi sisi kanan.
Menjalankan probing terhadap tabel hash menggunakan tabel kanan. Untuk entri yang cocok, keluarkan hasil agregasi sisi kiri dan sisi kanan. Untuk baris sisi kanan yang tidak cocok, keluarkan hasil dengan nilai NULL untuk agregat sisi kiri.
Setelah penggabungan, GroupJoin selesai. Tidak diperlukan lagi manajemen entri tabel hash.
Data spilling
GroupJoin menangani data spilling dengan pendekatan berbasis partisi, serupa dengan HASH JOIN dan HASH GROUP BY:
GroupJoin menggunakan pendekatan berbasis partisi.
Selama fase build, beberapa partisi disimpan di memori. Partisi lainnya ditulis ke file temporary di disk. Penulisan inkremental ke partisi tersebut juga ditulis ke file temporary yang sesuai. Filter Bloom dibuat untuk setiap partisi di disk guna menyaring secara efisien baris sisi kanan yang tidak cocok selama fase probe.
Selama fase probe, partisi di memori diproses terlebih dahulu menggunakan logika yang dijelaskan di atas. Untuk partisi di disk, filter Bloom memeriksa apakah data yang diminta termasuk dalam partisi tersebut. Jika ya, data ditulis ke file temporary yang sesuai. Jika tidak, data diabaikan atau dikeluarkan.
Setelah partisi di memori diproses, sistem memproses partisi di disk secara sekuensial. Setidaknya satu partisi muat di disk tanpa perlu dibagi menjadi sub-partisi, dan logika penggabungan serta agregasi yang sama tetap berlaku.
Makalah terkait
Dua makalah akademis menyediakan dasar teoretis dan praktis untuk GroupJoin di PolarDB.
Makalah 1 (2011): *Accelerating Queries with Group-By and Join by Groupjoin*
Makalah ini menetapkan kelayakan teoretis GroupJoin pada berbagai jenis kueri. Makalah ini menjelaskan skenario yang berlaku dan batasan fungsi agregat, tetapi pembahasannya bersifat abstrak dan minim detail implementasi.
Makalah 2 (2021): *A Practical Approach to Groupjoin and Nested Aggregates*
Dari tim database HyPer di Ludwig Maximilian University of Munich, makalah ini membahas implementasi GroupJoin yang efisien dalam database dalam memori. Kontribusi utama:
1. GroupJoin dalam dekorrelasi subkueri berkorelasi

Ketika subkueri berkorelasi mencakup GROUP BY, MagicSet dapat menghapus duplikat tabel dan memperkenalkan kombinasi JOIN + GROUP BY untuk mendekorrelasi subkueri — menciptakan konteks di mana GroupJoin berlaku. PolarDB mendukung dekorrelasi serupa dalam operasi yang diaktifkan IMCI, meskipun rencana eksekusi dengan objek anak bersama belum dihasilkan.
2. Penggabungan cepat (eager aggregation)
Agregasi data sisi kiri saat tabel hash sedang dibangun, alih-alih menyimpan muatan per entri untuk agregasi nanti. PolarDB mendukung eager aggregation dalam operasi yang diaktifkan IMCI.
3. Memoisasi untuk kontensi tabel hash konkuren
Dalam kasus ekstrem, semua baris sisi kanan cocok dengan entri tabel hash yang sama selama probing. Menjalankan berulang kali fungsi agregat seperti SUM() pada entri yang sama menciptakan kontensi — hambatan performa bahkan untuk operasi penambahan atomik.
Solusi dalam makalah: menjalankan perintah CAS (Compare-And-Swap) pada setiap entri untuk menetapkan thread pemilik. Thread yang gagal mendapatkan kepemilikan membuat tabel hash lokal untuk perhitungannya, lalu menggabungkan hasil ke tabel hash global.
4. Ketika GroupJoin bukan pilihan terbaik
Ketika selektivitas pada sisi kiri rendah (sebagian besar baris sisi kiri difilter setelah probing), muncul pertukaran:
Dengan eager aggregation: tidak ada muatan yang disimpan, menghemat memori — tetapi sebagian besar pekerjaan pra-agregasi terbuang sia-sia pada baris yang tidak akan dipilih.
Tanpa eager aggregation: penggunaan memori meningkat, mengimbangi manfaat eager aggregation.
Makalah ini merekomendasikan bahwa ketika selektivitas rendah, tunda agregasi: setelah penggabungan selesai, gunakan HASH GROUP BY untuk agregasi lokal pada kelompok hasil yang kecil. Memilih strategi yang tepat memerlukan pengoptimal untuk memperkirakan selektivitas dan kardinalitas.
Posisi PolarDB terhadap pertukaran ini
Ahli PolarDB tidak sependapat dengan kesimpulan makalah dalam dua aspek:
Pengukuran throughput: Makalah menggunakan tuples/detik. Eksperimen PolarDB, menggunakan dataset 1 GB yang sama, menunjukkan hasil berbeda karena perbedaan implementasi. Data PolarDB menunjukkan GroupJoin secara konsisten meningkatkan throughput kecuali untuk kombinasi RIGHT OUTER JOIN + GROUP BY RIGHT:
GroupJoin tidak berlaku untuk Q17 dalam skenario yang diaktifkan IMCI.
Kueri HASH JOIN + HASH GROUP BY GroupJoin Q3 130 MB 152 MB Q13 11 MB 33 MB Q18 315 MB 1 GB Efektivitas memoisasi: Eksperimen PolarDB menunjukkan kontensi entri tabel hash minimal dalam kueri TPC-H. Tabel hash lokal yang dibuat oleh memoisasi jarang diperlukan dalam praktik, artinya memoisasi memberikan performa mirip dengan HASH JOIN + HASH GROUP BY di lingkungan PolarDB. Perbandingan dalam makalah tidak menunjukkan keunggulan jelas untuk memoisasi.
Untuk operasi yang diaktifkan IMCI di PolarDB, pertukaran selektivitas kurang signifikan: PolarDB biasanya menggunakan tabel kecil untuk membangun tabel hash. Ketika selektivitas rendah dan eager aggregation digunakan, biayanya adalah waktu terbuang pada tabel kecil — hukuman minor. Inilah sebabnya GroupJoin hampir selalu lebih unggul dibandingkan HASH JOIN + HASH GROUP BY dalam skenario IMCI PolarDB.
GroupJoin dalam kueri TPC-H
TPC-H adalah benchmark standar untuk menguji kemampuan pemrosesan analitis (AP). GroupJoin berlaku untuk banyak dari 22 kuerinya, tetapi sebagian besar memerlukan modifikasi kueri agar dapat diaktifkan.
Q13
GroupJoin berlaku langsung untuk Q13 tanpa modifikasi:
SELECT
c_count,
count(*) AS custdist
FROM
(
SELECT
c_custkey,
count(o_orderkey) AS c_count
FROM
customer
LEFT OUTER JOIN orders ON c_custkey = o_custkey
AND o_comment NOT LIKE '%pending%deposits%'
GROUP BY
c_custkey
) c_orders
GROUP BY
c_count
ORDER BY
custdist DESC,
c_count DESC;Rencana eksekusi tanpa GroupJoin:

Rencana eksekusi dengan GroupJoin:

Q3
Q3 memerlukan penulisan ulang GROUP BY sebelum GroupJoin dapat digunakan:
SELECT
l_orderkey,
sum(l_extendedprice * (1 - l_discount)) AS revenue,
o_orderdate,
o_shippriority
FROM
customer,
orders,
lineitem
WHERE
c_mktsegment = 'BUILDING'
AND c_custkey = o_custkey
AND l_orderkey = o_orderkey
AND o_orderdate < DATE '1995-03-15'
AND l_shipdate > DATE '1995-03-15'
GROUP BY
l_orderkey,
o_orderdate,
o_shippriority
ORDER BY
revenue DESC,
o_orderdate
LIMIT 10;Rencana eksekusi asli dalam IMCI:

Kunci GROUP BY (l_orderkey, o_orderdate, o_shippriority) berbeda dari semua kunci gabungan, sehingga GroupJoin tidak berlaku secara langsung. Rantai ketergantungan fungsional berikut memungkinkan penulisan ulang:
Predikat gabungan
l_orderkey = o_orderkeyberarti bahwa dalam setiap baris hasil,l_orderkeydano_orderkeybernilai sama.Oleh karena itu,
GROUP BY l_orderkey, o_orderdate, o_shipprioritysetara denganGROUP BY o_orderkey, o_orderdate, o_shippriority.Karena
o_orderkeyadalah primary key tabelorders,o_orderdatedano_shipprioritysecara fungsional bergantung padao_orderkey.Oleh karena itu,
GROUP BY o_orderkey, o_orderdate, o_shipprioritydireduksi menjadiGROUP BY o_orderkey.
Mengganti klausa GROUP BY dengan GROUP BY o_orderkey mengaktifkan GroupJoin:

Pengoptimal MySQL dapat sebagian menurunkan ketergantungan fungsional tetapi tidak dapat sepenuhnya mereduksi ini menjadi GROUP BY o_orderkey secara otomatis. SQL Server secara teoretis dapat melakukan deduksi lengkap, meskipun hal ini belum sepenuhnya divalidasi dalam praktik yang diaktifkan IMCI. Deduksi ketergantungan fungsional yang sama berlaku untuk Q3, Q4, Q10, Q13, Q18, Q20, dan Q21. Ketika pengoptimal dapat melakukan deduksi lengkap, kunci GROUP BY dipersingkat dan agregasi menjadi lebih cepat.
Q10
Q10 memerlukan dua modifikasi sebelum GroupJoin dapat digunakan:
SELECT
c_custkey,
c_name,
sum(l_extendedprice * (1 - l_discount)) AS revenue,
c_acctbal,
n_name,
c_address,
c_phone,
c_comment
FROM
customer,
orders,
lineitem,
nation
WHERE
c_custkey = o_custkey
AND l_orderkey = o_orderkey
AND o_orderdate >= DATE '1993-10-01'
AND o_orderdate < DATE '1993-10-01' + INTERVAL '3' MONTH
AND l_returnflag = 'R'
AND c_nationkey = n_nationkey
GROUP BY
c_custkey,
c_name,
c_acctbal,
c_phone,
n_name,
c_address,
c_comment
ORDER BY
revenue DESC
LIMIT 20;Ganti kunci pengelompokan dengan
c_custkey(primary key tabelcustomer), menggunakan penalaran ketergantungan fungsional yang sama seperti Q3.Sesuaikan urutan penggabungan agar penggabungan tabel
customerberada di luar.
Modifikasi pertama selalu meningkatkan performa. Modifikasi kedua terkadang menimbulkan efek samping.
Q17
Q17 berisi subkueri berkorelasi:
SELECT
sum(l_extendedprice) / 7.0 AS avg_yearly
FROM
lineitem,
part
WHERE
p_partkey = l_partkey
AND p_brand = 'Brand#44'
AND p_container = 'WRAP PKG'
AND l_quantity < (
SELECT
0.2 * avg(l_quantity)
FROM
lineitem
WHERE
l_partkey = p_partkey
);Dua algoritma dekorrelasi menghasilkan rencana eksekusi yang tidak menggunakan GroupJoin:


Menggunakan MagicSet untuk dekorrelasi memperkenalkan keadaan antara yang kompatibel dengan GroupJoin:

Pendekatan ini juga ditunjukkan dalam Gambar 3 makalah 2:

PolarDB sebagian mendukung MagicSet sebagai metode dekorrelasi dalam skenario yang diaktifkan IMCI, tetapi belum menghasilkan rencana eksekusi dengan objek anak bersama. Akibatnya, GroupJoin tidak dapat digunakan untuk Q17 dalam skenario yang diaktifkan IMCI.
Q18
Q18 menerapkan GroupJoin setelah menyederhanakan GROUP BY. Contoh berikut menghilangkan subkueri IN dan klausa ORDER BY demi kejelasan:
SELECT
c_name,
c_custkey,
o_orderkey,
o_orderdate,
o_totalprice,
sum(l_quantity)
FROM
customer,
orders,
lineitem
WHERE
c_custkey = o_custkey
AND o_orderkey = l_orderkey
GROUP BY
c_name,
c_custkey,
o_orderkey,
o_orderdate,
o_totalpriceTerapkan reduksi berikut:
c_custkeyadalah primary keycustomer, sehinggac_namesecara fungsional bergantung padanya.o_orderkeyadalah primary keyorders, sehinggao_orderdatedano_totalpricesecara fungsional bergantung padanya. Oleh karena itu,GROUP BY c_name, c_custkey, o_orderkey, o_orderdate, o_totalpricedireduksi menjadiGROUP BY c_custkey, o_orderkey.Predikat gabungan
c_custkey = o_custkeyberarti hasil hanya berisi baris di manac_custkey = o_custkey. Oleh karena itu,GROUP BY c_custkey, o_orderkeydireduksi menjadiGROUP BY o_custkey, o_orderkey.Karena
o_orderkeysecara unik menentukano_custkey,GROUP BY o_custkey, o_orderkeydireduksi menjadiGROUP BY o_orderkey.
Kueri yang ditulis ulang:
SELECT
ANY_VALUE(c_name),
ANY_VALUE(c_custkey),
o_orderkey,
ANY_VALUE(o_orderdate),
ANY_VALUE(o_totalprice),
sum(l_quantity)
FROM
customer,
orders,
lineitem
WHERE
c_custkey = o_custkey
AND o_orderkey = l_orderkey
GROUP BY
o_orderkeyRencana eksekusi tanpa GroupJoin:

Rencana eksekusi dengan GroupJoin:

Memperpendek kunci GROUP BY juga bermanfaat bagi rencana eksekusi reguler yang tidak menggunakan GroupJoin.
Q20
Q20 berisi subkueri berkorelasi mirip Q17. Dekorrelasi MagicSet memperkenalkan keadaan antara yang kompatibel dengan GroupJoin sebelum MagicSet dihapus:
...
AND ps_availqty > (
SELECT
0.5 * sum(l_quantity) /* scalar aggregation */
FROM
lineitem
WHERE
l_partkey = ps_partkey /* correlated predicate 1 */
AND l_suppkey = ps_suppkey /* correlated predicate 2 */
AND l_shipdate >= '1993-01-01'
AND l_shipdate < DATE_ADD('1993-01-01', INTERVAL '1' YEAR)
)Kueri lainnya
Menurut makalah 1 dan makalah 2, GroupJoin juga berlaku untuk Q5, Q9, Q16, dan Q21 setelah modifikasi, tetapi langkah modifikasi spesifik tidak dijelaskan dalam makalah tersebut. Rencana eksekusi untuk GroupJoin pada kueri-kueri ini juga tidak tersedia di HyPer WebInterface (https://hyper-db.de/interface.html#).
Performa kueri
Banyak kueri TPC-H menggabungkan JOIN dan GROUP BY, menjadikannya kandidat untuk optimasi GroupJoin.
Makalah 1 membandingkan performa kueri untuk Q3, Q5, Q9, Q10, Q13, Q16, Q17, Q20, dan Q21 menggunakan data 1 GB. GroupJoin mengurangi latensi total dari 1.932 ms menjadi 1.295 ms pada kueri-kueri tersebut.

Makalah 2 membandingkan Q3, Q13, Q17, dan Q18 menggunakan data 1 GB, dengan tiga strategi:
Separate — JOIN standar diikuti oleh GROUP BY
Eager — GroupJoin dengan eager aggregation
Memoizing — GroupJoin dengan optimasi memoizing

Grafik garis dalam makalah menunjukkan dua pola pada Q3, Q13, Q17, dan Q18:
Performa memoizing mirip dengan HASH JOIN + HASH GROUP BY.
Eager aggregation mengungguli metode lain hanya pada Q13.
Hasil ini mendukung kesimpulan makalah bahwa strategi GroupJoin optimal bergantung pada karakteristik kueri dan bahwa pengoptimal harus memilih rencana eksekusi berdasarkan perkiraan selektivitas dan kardinalitas.
Eksperimen PolarDB mencapai kesimpulan berbeda. Dengan dataset 1 GB yang sama, PolarDB menunjukkan bahwa GroupJoin secara konsisten meningkatkan throughput (lihat tabel di Makalah terkait), dan kontensi minimal terjadi dalam kueri TPC-H. Tabel hash lokal yang dibuat oleh memoizing jarang diperlukan, sehingga memoizing memberikan performa sebanding dengan HASH JOIN + HASH GROUP BY dalam implementasi PolarDB.
Kesimpulan
GroupJoin menghilangkan pekerjaan redundan dengan menggabungkan HASH JOIN dan HASH GROUP BY menjadi satu operator. Dalam operasi yang diaktifkan IMCI pada PolarDB for MySQL, GroupJoin secara konsisten meningkatkan performa kueri kecuali ketika RIGHT OUTER JOIN dikombinasikan dengan GROUP BY pada sisi kanan.
GroupJoin tidak berlaku secara universal. GroupJoin memerlukan EQUAL JOIN + GROUP BY dengan kunci yang sesuai di salah satu sisi, batasan pada fungsi agregat, dan kondisi implementasi tertentu. Persyaratan ini membuat cakupan rencana eksekusi GroupJoin lebih sempit dan lebih kompleks untuk dipelihara.
Untuk memaksimalkan manfaat GroupJoin, generalisasi rencana eksekusinya agar mencakup pola kueri umum — terutama yang melibatkan penyederhanaan kunci GROUP BY berdasarkan ketergantungan fungsional, sebagaimana ditunjukkan oleh contoh TPC-H di atas.