Berikut skenario yang muncul baru-baru ini di tempat kerja.
Pertimbangkan tiga tabel, A, B, C.
A memiliki 3.000 baris; B memiliki 300.000.000 baris; dan C memiliki 2.000 baris.
Kunci asing didefinisikan: B (a_id), B (c_id).
Misalkan Anda memiliki kueri yang terlihat seperti ini:
select a.id, c.id
from a
join b on b.a_id = a.id
join c on c.id = b.c_id
Dalam pengalaman saya, MySQL dapat memilih untuk pergi ke C -> B -> A dalam kasus ini. C lebih kecil dari A dan B sangat besar, dan semuanya equijoins.
Masalahnya adalah MySQL tidak selalu memperhitungkan ukuran persimpangan antara (C.id dan B.c_id) vs (A.id dan B.a_id). Jika gabungan antara B dan C menghasilkan baris sebanyak B, maka itu adalah pilihan yang sangat buruk; jika memulai dengan A akan memfilter B ke baris sebanyak A, maka itu akan menjadi pilihan yang jauh lebih baik. straight_join
dapat digunakan untuk memaksa perintah ini seperti ini:
select a.id, c.id
from a
straight_join b on b.a_id = a.id
join c on c.id = b.c_id
Sekarang a
harus bergabung dulu b
.
Umumnya Anda ingin melakukan penggabungan dalam urutan yang meminimalkan jumlah baris dalam set yang dihasilkan. Jadi memulai dengan meja kecil dan menggabungkan sehingga gabungan yang dihasilkan juga akan kecil, sangat ideal. Hal-hal menjadi buah pir jika dimulai dengan meja kecil dan menggabungkannya ke meja yang lebih besar akhirnya menjadi sebesar meja besar.
Ini tergantung statistik. Jika distribusi data berubah, kalkulasi dapat berubah. Ini juga tergantung pada detail implementasi dari mekanisme gabungan.
Kasus terburuk yang pernah saya lihat untuk MySQL yang semuanya kecuali diperlukan straight_join
atau petunjuk indeks agresif adalah kueri yang memberi nomor pada banyak data dalam urutan ketat dengan penyaringan cahaya. MySQL sangat memilih untuk menggunakan indeks untuk filter apa pun dan menggabungkannya; ini masuk akal karena kebanyakan orang tidak mencoba mengurutkan seluruh database tetapi memiliki subset baris terbatas yang responsif terhadap kueri, dan mengurutkan subset terbatas jauh lebih cepat daripada memfilter seluruh tabel, tidak peduli apakah itu diurutkan atau tidak. Dalam hal ini, menempatkan gabungan langsung segera setelah tabel yang memiliki kolom terindeks yang ingin saya sortir pada hal-hal yang diperbaiki.
straight_join
.