it-swarm.asia

Di MySQL, apakah urutan kolom dalam klausa WHERE memengaruhi kinerja kueri?

Saya mengalami masalah kinerja pada permintaan basis data tertentu yang memiliki set hasil yang besar.

Kueri yang dimaksud, saya punya tiga ANDs dalam klausa WHERE

Apakah urutan klausa itu penting?

Seperti pada, jika saya menempatkan klausa ASI_EVENT_TIME pertama (karena itu akan menghapus sebagian besar hasil dari salah satu klausa.

Apakah itu akan meningkatkan waktu berjalan pada kueri?

PERTANYAAN:

SELECT DISTINCT  activity_seismo_info.* 
FROM `activity_seismo_info` 
WHERE 
    activity_seismo_info.ASI_ACTIVITY_ID IS NOT NULL  AND 
    activity_seismo_info.ASI_SEISMO_ID IN (43,44,...,259) AND 
    (
        activity_seismo_info.ASI_EVENT_TIME>='2011-03-10 00:00:00' AND 
        activity_seismo_info.ASI_EVENT_TIME<='2011-03-17 23:59:59'
    ) 

ORDER BY activity_seismo_info.ASI_EVENT_TIME DESC

JELASKAN kueri:

+----+-------------+---------+-------+---------------------------+--------------+---------+------+-------+-----------------------------+ 
| id | select_type | table   | type  | possible_keys             | key          | key_len | ref  | rows  | Extra                       |
+----+-------------+---------+-------+---------------------------+--------------+---------+------+-------+-----------------------------+ 
|  1 | SIMPLE      | act...o | range | act...o_FI_1,act...o_FI_2 | act...o_FI_1 | 5       | NULL | 65412 | Using where; Using filesort |
+----+-------------+---------+-------+---------------------------+--------------+---------+------+-------+-----------------------------+

Menggunakan:

PHP 5.2

MySQL 5.0.51a-3ubuntu5.4

Propel 1.3

Symfony 1.2.5

41
Patrick

Saya kira tidak. Pengoptimal kueri harus cukup pintar.

Anda dapat mencoba mengatur ulang klausa WHERE dan melihat bahwa EXPLAINS memberi tahu Anda hal yang sama dalam setiap kasus.


Tentang apa yang dapat dilakukan untuk mengoptimalkan kueri ini: Apakah ada indeks di ASI_EVENT_TIME? (ini yang paling penting menurut saya untuk kueri ini karena Anda juga mengurutkan hasil menggunakannya).

Apakah ada indeks pada dua bidang lainnya (ASI_SEISMO_ID dan ASI_ACTIVITY_ID)?

Akan sangat membantu jika Anda memposting struktur tabel.

26
ypercubeᵀᴹ

Dari dokumentasi :

Jika tabel memiliki indeks beberapa kolom, awalan paling kiri dari indeks dapat digunakan oleh pengoptimal untuk menemukan baris. Misalnya, jika Anda memiliki indeks tiga kolom di (col1, col2, col3), Anda telah mengindeks kemampuan pencarian di (col1), (col1, col2), dan (col1, col2, col3).

MySQL tidak dapat menggunakan indeks jika kolom tidak membentuk awalan paling kiri dari indeks.

Jadi ya, itu harus sama dengan urutan kolom dalam indeks gabungan .

15
Gaius

Tidak, itu tidak masalah.

Pengoptimal melakukan banyak transformasi sederhana langsung setelah mem-parsing SQL - ini adalah salah satunya.

10
Morgan Tocker

DI MANA foo DAN bar

mengoptimalkan sama dengan

DI MANA bar DAN foo

Namun,

WHERE tidak sama dengan # 1 DAN tidak sama dengan # 2

Tidak dapat mengoptimalkan kedua bagian. Sebagai contoh,

DI MANA ANTARA 1 dan 3 DAN b> 17

tidak dapat memanfaatkan INDEX (a, b) atau INDEX (b, a)

Untuk frasa berbeda, setiap '=' tes DAN bersama-sama dalam klausa WHERE digunakan terlebih dahulu, kemudian satu non - '=' (IN, ANTARA,>, dll) dapat ditangani. Tidak lebih dari satu dapat dioptimalkan secara efektif.

Kueri Anda memiliki 3 klausa seperti itu.

Ternyata, INDEX (EVENT_TIME) mungkin yang paling berguna - ini akan membantu dengan salah satu AND, dan mungkin digunakan untuk menghindari "filesort" untuk ORDER BY.

Jika tidak ada baris duplikat (mengapa ada?), Lalu singkirkan DISTINCT. Itu bahkan menyebabkan lebih banyak upaya.

Berikan SHOW CREATE TABLE dan SHOW TABLE STATUS saat mengajukan pertanyaan kinerja.

Perbarui ... Versi yang lebih baru (mis., MySQL 5.7) dapat, dalam beberapa situasi, memperlakukan IN( list of constants ) hampir seperti =. Untuk memainkannya dengan aman, patuhi pesanan ini (setiap bagian bersifat opsional):

  1. Sejumlah =.
  2. Beberapa INs.
  3. Paling banyak satu rentang.
8
Rick James

MySQL where optimization doc mengatakan:

Anda mungkin tergoda untuk menulis ulang pertanyaan Anda untuk membuat operasi aritmatika lebih cepat, sambil mengorbankan keterbacaan. Karena MySQL melakukan optimasi serupa secara otomatis , Anda sering dapat menghindari pekerjaan ini, dan meninggalkan kueri dalam bentuk yang lebih mudah dipahami dan dikelola. Beberapa optimasi yang dilakukan oleh MySQL mengikuti:

  • ...

  • Untuk setiap tabel di gabungan, WHERE yang lebih sederhana dibangun untuk mendapatkan evaluasi WHERE cepat untuk tabel dan juga untuk melewati baris sesegera mungkin .

  • Setiap indeks tabel dikueri, dan indeks terbaik digunakan kecuali pengoptimal percaya bahwa lebih efisien untuk digunakan pemindaian tabel . Pada suatu waktu, pemindaian digunakan berdasarkan apakah indeks terbaik membentang lebih dari 30% dari tabel, tetapi persentase tetap tidak lagi menentukan pilihan antara menggunakan indeks atau pemindaian. Pengoptimal sekarang lebih kompleks dan mendasarkan perkiraannya pada faktor-faktor tambahan seperti ukuran tabel, jumlah baris, dan ukuran blok I/O.

Dengan cara ini rasional bagi pengoptimal kueri untuk menghilangkan BAGAIMANA kami menggunakan kolom dalam kueri (Tidak hanya MySQL tetapi SQL adalah bahasa deklaratif dan harus melakukan apa yang kita inginkan bukan seperti yang kita inginkan).

Namun saya masih suka memiliki jenis yang sama untuk kolom kunci komposit dalam permintaan tetapi kadang-kadang tak terhindarkan misalnya ketika kita menggunakan ORM atau ActiveRecord, dalam beberapa kerangka kerja seperti yii2, menyesuaikan kriteria relasi akan ditambahkan pada akhir kondisi "aktif" tetapi kita masih membutuhkan kemampuan QueryBuilders di berbagai bagian aplikasi.

1
Alix