Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Apakah urutan bidang dalam klausa WHERE memengaruhi kinerja di MySQL?

SQL dirancang untuk menjadi bahasa deklaratif, bukan bahasa prosedural. Jadi pengoptimal kueri seharusnya tidak mempertimbangkan urutan predikat klausa mana dalam menentukan bagaimana menerapkannya.

Saya mungkin akan terlalu menyederhanakan diskusi berikut tentang pengoptimal kueri SQL. Saya menulis satu tahun yang lalu, di sepanjang baris ini (sangat menyenangkan!). Jika Anda benar-benar ingin menggali pengoptimalan kueri modern, lihat Penyetelan SQL , dari O'Reilly.

Dalam pengoptimal kueri SQL sederhana, pernyataan SQL pertama-tama dikompilasi menjadi pohon aljabar relasional operasi. Operasi ini masing-masing mengambil satu atau lebih tabel sebagai input dan menghasilkan tabel lain sebagai output. Pindai adalah pemindaian sekuensial yang membaca tabel dari database. Urutkan menghasilkan tabel yang diurutkan. Pilih menghasilkan tabel yang barisnya dipilih dari tabel lain menurut beberapa kondisi pemilihan. Proyek menghasilkan tabel dengan hanya kolom tertentu dari tabel lain. Produk Lintas mengambil dua tabel dan menghasilkan tabel keluaran yang terdiri dari setiap pasangan baris yang mungkin.

Yang membingungkan, klausa SQL SELECT dikompilasi menjadi aljabar relasional Proyek , sedangkan klausa WHERE berubah menjadi aljabar relasional Pilih . Klausa FROM berubah menjadi satu atau lebih Bergabung , masing-masing mengambil dua meja masuk dan menghasilkan satu meja keluar. Ada operasi aljabar relasional lainnya yang melibatkan himpunan serikat, persimpangan, perbedaan, dan keanggotaan, tetapi mari kita buat ini tetap sederhana.

Pohon ini sangat perlu dioptimalkan. Misalnya, jika Anda memiliki:

select E.name, D.name 
from Employee E, Department D 
where E.id = 123456 and E.dept_id = D.dept_id

dengan 5.000 karyawan di 500 departemen, mengeksekusi pohon yang tidak dioptimalkan akan secara membabi buta menghasilkan semua kemungkinan kombinasi dari satu Karyawan dan satu Departemen (Produk Silang ) lalu Pilih keluar hanya satu kombinasi yang dibutuhkan. Pemindaian Karyawan akan menghasilkan 5.000 tabel record, Scan Departemen akan menghasilkan 500 tabel record, Produk Silang dari dua tabel tersebut akan menghasilkan 2.500.000 tabel record, dan Pilih pada E.id akan mengambil 2.500.000 tabel catatan itu dan membuang semua kecuali satu, catatan yang diinginkan.

[Pemroses kueri yang sebenarnya akan mencoba untuk tidak mewujudkan semua tabel perantara ini dalam memori tentunya.]

Jadi pengoptimal kueri berjalan di atas pohon dan menerapkan berbagai pengoptimalan. Salah satunya adalah memecah setiap Pilih ke dalam rantai Pilihan , satu untuk setiap Pilih original asli kondisi tingkat atas, yang dan-ed bersama-sama. (Ini disebut "bentuk normal penghubung".) Kemudian individu yang lebih kecil Memilih dipindahkan di sekitar pohon dan digabungkan dengan operasi aljabar relasional lainnya untuk membentuk operasi yang lebih efisien.

Dalam contoh di atas, pengoptimal pertama-tama menekan tombol Pilih pada E.id =123456 di bawah Cross Product yang mahal operasi. Ini berarti Produk Silang hanya menghasilkan 500 baris (satu untuk setiap kombinasi karyawan itu dan satu departemen). Kemudian tingkat atas Pilih untuk E.dept_id =D.dept_id menyaring 499 baris yang tidak diinginkan. Tidak buruk.

Jika ada indeks pada kolom Employee's id, maka pengoptimal dapat menggabungkan Scan Karyawan dengan Pilih pada E.id =123456 untuk membentuk indeks cepat Pencarian . Ini berarti bahwa hanya satu baris Karyawan yang dibaca ke dalam memori dari disk, bukan 5.000. Banyak hal yang terlihat.

Pengoptimalan utama terakhir adalah mengambil Pilih pada E.dept_id =D.dept_id dan gabungkan dengan Produk Silang . Ini mengubahnya menjadi aljabar relasional Equijoin operasi. Ini tidak berbuat banyak dengan sendirinya. Tetapi jika ada indeks di Department.dept_id, maka tingkat yang lebih rendah berurutan Scan Departemen memberi makan Equijoin dapat diubah menjadi Pencarian indeks yang sangat cepat dari catatan Departemen satu karyawan kami.

Pengoptimalan yang lebih rendah melibatkan mendorong Proyek operasi turun. Jika level teratas kueri Anda hanya membutuhkan E.name dan D.name, dan kondisinya membutuhkan E.id, E.dept_id, dan D.dept_id, maka Scan operasi tidak harus membangun tabel perantara dengan semua kolom lainnya, menghemat ruang selama eksekusi kueri. Kami telah mengubah kueri yang sangat lambat menjadi dua pencarian indeks dan tidak banyak lagi.

Mendapatkan lebih banyak ke pertanyaan awal, katakanlah Anda punya:

select E.name 
from Employee E 
where E.age > 21 and E.state = 'Delaware'

Pohon aljabar relasional yang tidak dioptimalkan, ketika dijalankan, akan Memindai 5.000 karyawan dan menghasilkan, katakanlah, 126 karyawan di Delaware yang berusia lebih dari 21 tahun. Pengoptimal kueri juga memiliki gambaran kasar tentang nilai dalam database. Mungkin tahu bahwa kolom E.state memiliki 14 negara bagian bahwa perusahaan memiliki lokasi, dan sesuatu tentang distribusi E.age. Jadi pertama-tama ia melihat apakah salah satu bidang diindeks. Jika E.state, masuk akal untuk menggunakan indeks itu untuk hanya memilih sejumlah kecil karyawan yang dicurigai oleh prosesor kueri di Delaware berdasarkan statistik terakhir yang dihitung. Jika hanya E.age, prosesor kueri mungkin memutuskan bahwa itu tidak sepadan, karena 96% dari semua karyawan berusia 22 tahun ke atas. Jadi jika E.state diindeks, pemroses kueri kami memecah Pilih dan menggabungkan E.state ='Delaware' dengan Scan untuk mengubahnya menjadi Pemindaian Indeks yang jauh lebih efisien .

Katakanlah dalam contoh ini bahwa tidak ada indeks di E.state dan E.age. Gabungan Pilih operasi berlangsung setelah "Pemindaian" Karyawan secara berurutan. Apakah ada perbedaan kondisi di Pilih dilakukan terlebih dahulu? Mungkin tidak banyak. Pemroses kueri mungkin membiarkannya dalam urutan asli dalam pernyataan SQL, atau mungkin sedikit lebih canggih dan melihat biaya yang diharapkan. Dari statistik, itu akan kembali menemukan bahwa kondisi E.state ='Delaware' harus lebih selektif, sehingga akan membalikkan kondisi dan melakukan itu terlebih dahulu, sehingga hanya ada 126 E.age> 21 perbandingan bukannya 5.000 . Atau mungkin disadari bahwa perbandingan kesetaraan string jauh lebih mahal daripada perbandingan bilangan bulat dan biarkan urutannya saja.

Bagaimanapun, semua ini sangat kompleks dan urutan kondisi sintaksis Anda sangat kecil kemungkinannya untuk membuat perbedaan. Saya tidak akan mengkhawatirkannya kecuali Anda memiliki masalah kinerja nyata dan vendor database Anda menggunakan urutan kondisi sebagai petunjuk.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Snow Leopard + Ruby 1.9.1 + Permata MySQL =Masalah besar

  2. MySQL TIDAK DALAM permintaan tidak berfungsi

  3. Apa praktik terbaik untuk menyimpan data khusus untuk Wordpress

  4. menjebak peringatan MySql

  5. Jumlah item MySQL di dalam klausa