Kapan menggunakan sub-kueri SQL versus gabungan standar?

Saya sedang menulis ulang beberapa kueri SQL yang ditulis dengan buruk dan mereka menggunakan sub-kueri secara berlebihan. Saya mencari praktik terbaik terkait penggunaan sub-kueri.

Bantuan apa pun akan dihargai.


person Brad Krusemark    schedule 25.01.2011    source sumber
comment
Bukan berarti tidak ada solusi yang tepat -- masalahnya adalah pertanyaan ini terlalu luas untuk dijawab secara masuk akal. Tidak ada jaminan bahwa apa yang berfungsi pada satu database (MySQL), berfungsi sama persis di database lain. Aturan paling sederhana adalah jika kolom dari subkueri berada di kumpulan hasil akhir, gunakan GABUNG -- ini adalah cara paling optimal untuk mendapatkan data dari dua tabel. Jika tidak, subquery baik-baik saja tetapi subquery yang berkorelasi dapat menyebabkan masalah (meskipun tidak dengan EXISTS).   -  person OMG Ponies    schedule 26.01.2011
comment
Atas dasar apa Anda menyatakan bahwa sub-kueri digunakan secara berlebihan? Tampaknya aneh untuk memutuskan bahwa dan kemudian meminta informasi tentang praktik terbaik dalam menggunakan subkueri.   -  person Larry Lustig    schedule 26.01.2011
comment
Kemungkinan duplikat Gabung vs. sub-kueri   -  person Ciro Santilli 新疆再教育营六四事件ۍ    schedule 12.06.2016
comment
@OMGPonies Aturan paling sederhana Anda cocok dengan AskTom, keduanya (gabungan/subkueri) berbeda secara semantik. * Gunakan subquery ketika Anda tidak memerlukan kolom dari tabel yang direferensikan dalam subquery. * Gunakan join ketika Anda memerlukan beberapa kolom. pilih * dari emp dimana deptno masuk ( pilih deptno dari dept ); akan lebih baik daripada memilih emp.* dari emp, dept dimana emp.deptno = dept.deptno; Dan ingat, subquery tidak bisa begitu saja digantikan dengan join (dan sebaliknya), karena sering kali menghasilkan JAWABAN YANG BERBEDA.   -  person ExcessOperatorHeadspace    schedule 14.05.2019


Jawaban (3)


Subkueri biasanya baik-baik saja kecuali subkueri tersebut merupakan subkueri yang bergantung (juga dikenal sebagai subkueri yang berkorelasi). Jika Anda hanya menggunakan subkueri independen dan subkueri tersebut menggunakan indeks yang sesuai, maka subkueri tersebut akan berjalan dengan cepat. Jika Anda memiliki subkueri dependen, Anda mungkin mengalami masalah kinerja karena subkueri dependen biasanya perlu dijalankan satu kali untuk setiap baris di kueri luar. Jadi jika query luar Anda memiliki 1000 baris, subquery akan dijalankan 1000 kali. Di sisi lain, subkueri independen biasanya hanya perlu dievaluasi satu kali.

Jika Anda tidak yakin apa yang dimaksud dengan subkueri yang bergantung atau independen, inilah aturan praktisnya - jika Anda dapat mengambil subkueri tersebut, menghapusnya dari konteksnya, menjalankannya, dan mendapatkan hasil yang ditetapkan, maka itu adalah independent subquery.

Jika Anda mendapatkan kesalahan sintaksis karena merujuk ke beberapa tabel di luar subkueri, maka itu adalah dependent subquery.

Aturan umum tentu saja mempunyai beberapa pengecualian. Misalnya:

  • Banyak pengoptimal dapat mengambil subkueri dependen dan menemukan cara untuk menjalankannya secara efisien sebagai GABUNG. Misalnya query NOT EXISTS mungkin menghasilkan rencana query ANTI JOIN, sehingga tidak selalu lebih lambat dibandingkan menulis query dengan JOIN.
  • MySQL memiliki bug di mana subkueri independen di dalam ekspresi IN salah diidentifikasi sebagai a subkueri dependen sehingga rencana kueri suboptimal digunakan. Hal ini tampaknya telah diperbaiki di versi terbaru MySQL.

Jika kinerja menjadi masalah, ukur kueri spesifik Anda dan lihat mana yang terbaik bagi Anda.

person Mark Byers    schedule 25.01.2011
comment
Yang Anda maksud dengan berkorelasi berisi referensi ke kolom di kueri luar? - person El Ronnoco; 26.01.2011
comment
Banyak pengoptimal dapat mengambil subkueri dependen dan menemukan cara untuk menjalankannya secara efisien -- Saya setuju dengan pernyataan ini, dan ini meniadakan seluruh argumen Anda, yaitu subkueri yang berkorelasi buruk kecuali jika tidak buruk. - person onedaywhen; 21.09.2011

Tidak ada solusi terbaik di sini. Setiap penggunaan harus dinilai secara independen. Ada beberapa kasus di mana subkueri yang berkorelasi jelas tidak efisien, yang di bawah ini lebih baik ditulis sebagai GABUNG

select nickname, (select top 1 votedate from votes where user_id=u.id order by 1 desc)
from users u

Di sisi lain, kueri EXISTS dan NOT EXISTS akan menang atas JOIN.

select ...
where NOT EXISTS (.....)

Biasanya lebih cepat dari

select ...
FROM A LEFT JOIN B
where B.ID is null

Namun generalisasi ini pun bisa saja tidak benar untuk skema dan distribusi data tertentu.

person RichardTheKiwi    schedule 25.01.2011

Sayangnya jawabannya sangat tergantung pada sql server yang Anda gunakan. Secara teori, gabungan lebih baik dari sudut pandang teori relasional murni. Mereka membiarkan server melakukan hal yang benar dan memberi mereka kontrol lebih besar sehingga pada akhirnya bisa lebih cepat. Jika server diimplementasikan dengan baik. Dalam praktiknya, beberapa server SQL berkinerja lebih baik jika Anda mengelabuinya agar mengoptimalkan kuerinya melalui sub-kueri dan sejenisnya.

person Wes Hardaker    schedule 25.01.2011
comment
Beberapa sub-kueri juga dapat dipromosikan menjadi gabungan (tentu saja bergantung pada server). Untuk sebagian besar kasus, menurut saya sambungan lebih cocok dengan kepala saya. - person ; 26.01.2011
comment
Tidak, jika server diimplementasikan dengan baik maka server akan mengenali cara tercepat untuk melakukan JOIN atau sub-kueri dan menghasilkan rencana eksekusi optimal. Jika JOIN dan sub-query secara aljabar sama, maka server yang diimplementasikan dengan baik akan menghasilkan rencana eksekusi yang sama. - person Larry Lustig; 26.01.2011
comment
Ya... Semua benar. Jika sebuah server diimplementasikan dengan sempurna, ia akan selalu mengoptimalkan kueri Anda yang rusak juga ;-) Tapi... itulah sebagian besar maksud saya: hampir semua server sql bekerja lebih baik jika Anda membuat kueri sesuai dengan perilakunya. Ini adalah kebenaran yang disayangkan. Secara umum, semakin lama suatu produk ada, semakin besar kemungkinan produk tersebut berfungsi lebih baik, tidak peduli bagaimana Anda menyusun kueri Anda. Namun hal itu pun tidak selalu benar. - person Wes Hardaker; 26.01.2011
comment
bergabung lebih baik dari sudut pandang teori relasional murni -- omong kosong. Pertimbangkan bahwa SQL belum lengkap dalam kaitannya dengan aljabar Codd sampai dukungan untuk subkueri ditambahkan. - person onedaywhen; 21.09.2011