MySQL memiliki masalah umum dengan kueri pengoptimalan yang melibatkan subkueri yang berkorelasi, atau subpilihan. Hingga versi 5.6.5, subquery tidak terwujud, namun akan mewujudkan tabel turunan yang digunakan dalam gabungan.
Intinya ini berarti bahwa ketika Anda menggunakan join, pertama kali subquery ditemui MySQL akan melakukan hal berikut:
SELECT code1 FROM myTable GROUP BY code1 HAVING COUNT(code1) > 1
Dan simpan hasilnya di tabel sementara (yang di-hash untuk membuat pencarian lebih cepat), lalu untuk setiap nilai di myTable
itu akan mencari tabel sementara untuk melihat apakah kodenya ada di sana.
Namun, sejak Anda menggunakan IN
subquery tidak terwujud dan ditulis ulang seperti:
SELECT t1.code1, t1.code2
FROM myTable t1
WHERE EXISTS
( SELECT t2.code1
FROM myTable t2
WHERE t2.Code1 = t1.Code1
GROUP BY t2.code1
HAVING COUNT(t2.code1) > 1
)
Artinya untuk setiap code
di myTable
, itu menjalankan subquery lagi. Yang ketika kueri luar Anda sangat sempit baik-baik saja, karena lebih efisien untuk hanya menjalankan subkueri beberapa kali, daripada menjalankannya untuk semua nilai dan menyimpan hasilnya dalam tabel sementara, namun ketika kueri luar Anda lebar, hasilnya dalam kueri dalam yang dieksekusi berkali-kali, dan di sinilah perbedaan kinerja dimulai.
Jadi untuk jumlah baris Anda, alih-alih menjalankan subkueri ~30.000 kali, Anda menjalankannya sekali, lalu mencari ~30.000 baris terhadap tabel sementara yang di-hash dengan hanya 400 baris masuk. Ini akan menjelaskan perbedaan kinerja yang begitu drastis.
Artikel ini ada di dokumen online menjelaskan optimasi subquery secara lebih mendalam.