Bagaimana Anda membuat MySQL menggunakan indeks untuk kueri tampilan? Jawaban singkatnya, berikan indeks yang dapat digunakan MySQL.
Dalam hal ini, indeks optimal kemungkinan merupakan indeks "penutup":
... ON highscores (player, happened_in, score)
Kemungkinan MySQL akan menggunakan indeks itu, dan EXPLAIN akan menampilkan:"Using index"
karena WHERE player = 24
(predikat kesetaraan pada kolom terdepan dalam indeks. GROUP BY happened_id
(kolom kedua dalam indeks), memungkinkan MySQL untuk mengoptimalkannya menggunakan indeks untuk menghindari operasi pengurutan. Termasuk score
kolom dalam indeks akan memungkinkan kueri untuk memenuhi sepenuhnya dari indeks, tanpa harus mengunjungi (mencari) halaman data yang direferensikan oleh indeks.
Itu jawaban cepatnya. Jawaban yang lebih panjang adalah bahwa MySQL sangat tidak mungkin menggunakan indeks dengan kolom utama happened_id
untuk kueri tampilan.
Mengapa tampilan menyebabkan masalah kinerja
Salah satu masalah yang Anda miliki dengan tampilan MySQL adalah MySQL tidak "mendorong" predikat dari kueri luar ke dalam kueri tampilan.
Kueri luar Anda menentukan WHERE happened_in = 2006
. Pengoptimal MySQL tidak mempertimbangkan predikat saat menjalankan "kueri tampilan" dalam. Kueri untuk tampilan itu dieksekusi secara terpisah, sebelum kueri luar. Kumpulan hasil dari eksekusi kueri itu "terwujud"; yaitu, hasilnya disimpan sebagai tabel MyISAM perantara. (MySQL menyebutnya sebagai "tabel turunan", dan nama yang mereka gunakan masuk akal, ketika Anda memahami operasi yang dilakukan MysQL.)
Intinya adalah bahwa indeks yang telah Anda tetapkan di happened_in
tidak digunakan oleh MySQL saat menjalankan kueri yang membentuk definisi tampilan.
Setelah "tabel turunan" perantara dibuat, MAKA kueri luar dijalankan, menggunakan "tabel turunan" itu sebagai sumber baris. Saat kueri luar itu berjalan, happened_in = 2006
predikat dievaluasi.
Perhatikan bahwa semua baris dari kueri tampilan disimpan, yang (dalam kasus Anda) adalah baris untuk SETIAP nilai happened_in
, bukan hanya yang Anda tentukan predikat kesetaraan di kueri luar.
Cara kueri tampilan diproses mungkin "tidak terduga" oleh beberapa orang, dan ini adalah salah satu alasan bahwa menggunakan "tampilan" di MySQL dapat menyebabkan masalah kinerja, dibandingkan dengan cara kueri tampilan diproses oleh database relasional lainnya.
Meningkatkan kinerja kueri tampilan dengan indeks penutup yang sesuai
Mengingat definisi tampilan dan kueri Anda, yang terbaik yang akan Anda dapatkan adalah metode akses "Menggunakan indeks" untuk kueri tampilan. Untuk mendapatkannya, Anda memerlukan indeks penutup, mis.
... ON highscores (player, happened_in, score).
Itu kemungkinan merupakan indeks yang paling bermanfaat (dari segi kinerja) untuk definisi tampilan yang ada dan kueri yang ada. player
kolom adalah kolom terdepan karena Anda memiliki predikat kesetaraan pada kolom tersebut dalam kueri tampilan. happened_in
kolom berikutnya, karena Anda memiliki operasi GROUP BY pada kolom itu, dan MySQL akan dapat menggunakan indeks ini untuk mengoptimalkan operasi GROUP BY. Kami juga menyertakan score
kolom, karena itu adalah satu-satunya kolom lain yang dirujuk dalam kueri Anda. Itu membuat indeks menjadi indeks "penutup", karena MySQL dapat memenuhi kueri itu langsung dari halaman indeks, tanpa perlu mengunjungi halaman apa pun di tabel yang mendasarinya. Dan ada baiknya kita keluar dari rencana kueri itu:"Menggunakan indeks" tanpa "Menggunakan filesort".
Bandingkan kinerja dengan kueri mandiri tanpa tabel turunan
Anda dapat membandingkan rencana eksekusi untuk kueri Anda dengan tampilan vs. kueri mandiri yang setara:
SELECT player
, MAX(score) AS highest_score
, happened_in
FROM highscores
WHERE player = 24
AND happened_in = 2006
GROUP
BY player
, happened_in
Kueri mandiri juga dapat menggunakan indeks penutup mis.
... ON highscores (player, happened_in, score)
tetapi tanpa perlu mewujudkan tabel MyISAM perantara.
Saya tidak yakin bahwa jawaban sebelumnya memberikan jawaban langsung atas pertanyaan yang Anda ajukan.
T:Bagaimana saya membuat MySQL menggunakan INDEX untuk kueri tampilan?
J:Tentukan INDEX yang sesuai yang dapat digunakan oleh kueri tampilan.
Jawaban singkatnya adalah memberikan "indeks penutup" (indeks mencakup semua kolom yang dirujuk dalam kueri tampilan). Kolom utama dalam indeks itu harus kolom yang direferensikan dengan predikat kesetaraan (dalam kasus Anda, kolom player
akan menjadi kolom terdepan karena Anda memiliki player = 24
predikat dalam kueri. Juga, kolom yang dirujuk dalam GROUP BY harus menjadi kolom terdepan dalam indeks, yang memungkinkan MySQL untuk mengoptimalkan GROUP BY
operasi, dengan memanfaatkan indeks daripada menggunakan operasi pengurutan.
Poin kuncinya di sini adalah bahwa kueri tampilan pada dasarnya adalah kueri yang berdiri sendiri; hasil dari kueri tersebut disimpan dalam tabel "turunan" perantara (tabel MyISAM yang dibuat saat kueri terhadap tampilan dijalankan.
Menggunakan tampilan di MySQL tidak selalu merupakan "ide yang buruk", tetapi saya akan sangat memperingatkan mereka yang memilih untuk menggunakan tampilan dalam MySQL untuk MENYADARI bagaimana MySQL memproses kueri yang merujuk pada tampilan tersebut. Dan cara MySQL memproses kueri tampilan berbeda (secara signifikan) dari cara kueri tampilan ditangani oleh database lain (mis. Oracle, SQL Server).