Apakah ada perbedaan kinerja antara dua contoh kueri ini?
Pertanyaan 1:
select count(*)
from table1 a
join table2 b
on b.key_col=a.key_col
where b.tag = 'Y'
Pertanyaan 2;
select count(*)
from table1 a
join table2 b
on b.key_col=a.key_col
and b.tag = 'Y'
Perhatikan satu-satunya perbedaan adalah penempatan kondisi tambahan; yang pertama menggunakan WHERE
klausa dan yang kedua menambahkan kondisi ke ON
klausa.
Ketika saya menjalankan kueri ini pada sistem Teradata saya, rencana jelaskan identik dan langkah GABUNG menunjukkan kondisi tambahan dalam setiap kasus. Namun, pada pertanyaan SO mengenai MySQL ini, salah satu jawaban menyarankan bahwa gaya kedua lebih disukai karena WHERE
pemrosesan terjadi setelah gabungan dibuat.
Apakah ada aturan umum yang harus diikuti ketika pengkodean pertanyaan seperti ini? Saya kira itu harus tergantung platform karena jelas tidak membuat perbedaan pada database saya, tapi mungkin itu hanya fitur Teradata. Dan jika itu adalah tergantung platform, saya ingin sangat banyak untuk mendapatkan beberapa referensi dokumentasi; Saya benar-benar tidak tahu harus mencari apa.
sumber
Jawaban:
Menurut Bab 9 (Parser dan Pengoptimal), Buku Memahami MySQL Internal oleh Sasha Pachev
di sini adalah rincian evaluasi permintaan sebagai tugas-tugas berikut:
ORDER BY
danGROUP BY
.Pada halaman yang sama, dikatakan sebagai berikut:
EPILOG
Karena kunci yang ada, jumlah data, dan ekspresi kueri, MySQL Joins kadang-kadang dapat melakukan hal-hal untuk kebaikan kita sendiri (atau untuk membalas kita) dan menghasilkan hasil yang tidak kita harapkan dan tidak dapat dengan cepat dijelaskan.
Saya menulis tentang quirkiness ini sebelumnya
Jan 23, 2013
: Masalah dengan kueri UPDATE bersarangFeb 22, 2011
: Masalah dengan subquery MySQLkarena Pengoptimal Kueri MySQL dapat menghilangkan kunci tertentu selama evaluasi permintaan.
Komentar @ Phil membantu saya melihat cara mengirim jawaban ini (+1 untuk komentar @ Phil)
Komentar @ ypercube (+1 untuk yang ini juga) adalah versi ringkas dari posting saya karena Pengoptimal Permintaan MySQL adalah primitif. Sayangnya, itu harus karena berurusan dengan mesin penyimpanan luar.
KESIMPULAN
Adapun pertanyaan Anda yang sebenarnya, Pengoptimal Kueri MySQL akan menentukan metrik kinerja setiap permintaan saat selesai
Anda mungkin harus memaksa urutan eksekusi dengan menulis ulang (refactoring) kueri
Ini Query pertama yang Anda berikan
Coba tulis ulang untuk mengevaluasi WHERE dulu
Itu pasti akan mengubah rencana EXPLAIN. Itu bisa menghasilkan hasil yang lebih baik atau lebih buruk.
Saya pernah menjawab pertanyaan di StackOverflow di mana saya menerapkan teknik ini. EXPLAIN itu menghebohkan tetapi performanya dinamit. Ini hanya berfungsi karena memiliki indeks yang benar hadir dan penggunaan LIMIT dalam subquery .
Seperti harga saham, ketika datang ke Permintaan dan mencoba untuk mengungkapkannya, pembatasan berlaku, hasil dapat bervariasi, dan kinerja masa lalu tidak menunjukkan hasil di masa depan.
sumber
Untuk Oracle, karena mySQL memiliki deskripsi yang panjang, kami memiliki 2 cara tingkat tinggi untuk memanfaatkan pengoptimal.
Pertama adalah Optimalisasi Berbasis Aturan (atau RBO). Oracle memiliki 15 aturan set-in-stone yang masing-masing kueri diuraikannya mencoba untuk mengikuti dalam urutan yang ditetapkan. Jika tidak dapat menghasilkan kueri yang dioptimalkan dari aturan 1, itu akan bergerak maju ke aturan 2 dan seterusnya hingga mencapai aturan 15.
untuk info lebih lanjut: https://docs.oracle.com/cd/B10500_01/server.920/a96533/rbo.htm
Ini memengaruhi kernel Oracle RDBMS dari 11.1 dan di bawahnya yang belum dikonversi ke Cost Based Optimizer (alias CBO). Oracle 11.2 dan lebih tinggi memerlukan pengoptimal CBO, tetapi dapat memaksa ID Sql tertentu untuk mengoptimalkan dalam metode RBO lama jika pengguna menginginkannya.
CBO untuk Oracle 11.1+ alih-alih membuat beberapa rencana eksekusi untuk SQL ID yang sama dan menjalankan yang dengan biaya yang paling tidak diantisipasi secara keseluruhan. Ini memanfaatkan banyak logika dari RBO, tetapi menganalisis statistik tabel untuk membuat biaya rencana eksekusi dinamis untuk setiap operasi yang harus dilakukan DB untuk memberikan data kepada pengguna akhir. Melaksanakan pemindaian tabel penuh pada tabel yang sangat besar benar-benar mahal; menjalankan pemindaian tabel penuh di atas meja dengan 10 baris itu murah. Dalam RBO ini dianggap operasi yang sama.
untuk info lebih lanjut: https://oracle-base.com/articles/misc/cost-based-optimizer-and-database-statistics
Untuk contoh permintaan spesifik Anda: Oracle kemungkinan akan mem-parsing informasi untuk membuat rencana eksekusi yang berbeda dan dengan demikian satu akan secara teknis lebih baik daripada yang lain. Namun, ini bisa menjadi perbedaan minimal. Melihat itu, baik Oracle RBO dan CBO ingin meminta 1 lebih karena menjalankan pada gabungan dengan kondisi kurang dan kemudian menyaring kolom tertentu dari tabel sementara yang dibuat dari gabungan.
sumber
Jika Anda memiliki dua pertanyaan dan Anda berpikir bahwa mereka setara maka yang berikut ini dapat terjadi:
ada rencana eksekusi yang berbeda. Kami memiliki dua sub-bagian di sini.
2.1 Permintaan memiliki rencana pelaksanaan yang berbeda tetapi kedua rencana memiliki kinerja yang sama baiknya. Itu baik juga. Tidak perlu bahwa untuk permintaan setara, rencana yang sama harus dihasilkan. Tetapi kinerjanya harus sama. Dan sekali lagi kami berharap ini adalah yang terbaik.
2.2 Permintaan memiliki rencana pelaksanaan yang berbeda dan satu rencana lebih baik daripada yang lain. Lagi-lagi kami memiliki sub-bagian:
2.2.1 Paket berbeda karena kueri tidak setara. Jadi hati-hati periksa apakah mereka benar-benar setara. Dalam kasus Anda mereka benar-benar setara.
2.2.2 Paket berbeda tetapi kueri sama. Ini berarti pengoptimal tidak cukup matang. Di dunia yang sempurna dengan pengoptimal yang sempurna ini seharusnya tidak terjadi. Jadi ya, itu tergantung platform dan Anda harus mempelajari dokumen spesifik platform untuk mencari tahu mengapa ini terjadi.
2.2.3 Paket berbeda, kueri sama, perangkat lunak database memiliki bug.
sumber