it-swarm.it

In MySQL, l'ordine delle colonne in una clausola WHERE influenza le prestazioni della query?

Sto riscontrando problemi di prestazioni su determinate query del database che hanno grandi possibili set di risultati.

La query in questione, ho tre ANDs nella clausola WHERE

L'ordine delle clausole è importante?

Come in, se inserissi prima la clausola ASI_EVENT_TIME (poiché ciò eliminerebbe la maggior parte dei risultati da una qualsiasi delle clausole.

Ciò migliorerà il tempo di esecuzione della query?

DOMANDA:

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

SPIEGAZIONE della query:

+----+-------------+---------+-------+---------------------------+--------------+---------+------+-------+-----------------------------+ 
| 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 |
+----+-------------+---------+-------+---------------------------+--------------+---------+------+-------+-----------------------------+

Usando:

PHP 5.2

MySQL 5.0.51a-3ubuntu5.4

Propel 1.3

Symfony 1.2.5

41
Patrick

Non la penso così. Query Optimizer dovrebbe essere abbastanza intelligente.

Puoi provare a riorganizzare le clausole WHERE e vedere che EXPLAINS ti dice lo stesso in ogni caso.


Informazioni su cosa si può fare per ottimizzare questa query: esiste un indice su ASI_EVENT_TIME? (questa è la cosa più cruciale che penso per questa query in quanto si ordinano anche i risultati utilizzandola).

Ci sono indici sugli altri due campi (ASI_SEISMO_ID e ASI_ACTIVITY_ID)?

Sarebbe utile se hai pubblicato la struttura della tabella.

26
ypercubeᵀᴹ

Da la documentazione :

Se la tabella ha un indice a più colonne, qualsiasi ottimizzatore all'estrema sinistra dell'indice può essere utilizzato dall'ottimizzatore per trovare le righe. Ad esempio, se hai un indice a tre colonne su (col1, col2, col3), hai capacità di ricerca indicizzata su (col1), (col1, col2) e (col1, col2, col3).

MySQL non può utilizzare un indice se le colonne non formano un prefisso più a sinistra dell'indice.

Quindi sì, dovrebbe essere uguale all'ordine delle colonne in un indice composto .

15
Gaius

No, non importa.

L'ottimizzatore esegue una serie di semplici trasformazioni subito dopo aver analizzato l'SQL: questa è una di queste.

10
Morgan Tocker

DOVE foo E bar

ottimizza lo stesso di

DOVE bar E foo

Però,

DOVE non uguale # 1 E non uguale # 2

Impossibile ottimizzare entrambe le parti. Per esempio,

DOVE a TRA 1 e 3 E b> 17

non può fare buon uso di INDICE (a, b) o INDICE (b, a)

Per esprimerlo diversamente, tutti i test "=" AND messi insieme nella clausola WHERE vengono utilizzati per primi, quindi uno non - '=' (IN, TRA,>, ecc.) Può essere gestito. Non più di uno può essere efficacemente ottimizzato.

La tua query ha 3 di tali clausole.

A quanto pare, INDEX (EVENT_TIME) è probabilmente il più utile - aiuterà con uno degli AND, e potrebbe essere usato per evitare "filesort" per ORDER BY.

Se non ci sono righe duplicate (perché diavolo ci sarebbe?), Quindi sbarazzarsi di DISTINCT. Ciò provoca uno sforzo ancora maggiore.

Fornire SHOW CREATE TABLE e SHOW TABLE STATUS quando si pongono domande sulla performance.

Aggiornamento ... Le versioni più recenti (ad es. MySQL 5.7) possono, in alcune situazioni, trattare IN( list of constants ) quasi come =. Per giocare in sicurezza, segui questo ordine (ogni parte è facoltativa):

  1. Qualsiasi numero di =.
  2. Alcuni INs.
  3. Al massimo un intervallo.
8
Rick James

MySQL dove ottimizzazione doc dice:

Potresti essere tentato di riscrivere le tue domande per velocizzare le operazioni aritmetiche, sacrificando la leggibilità. Poiché MySQL esegue automaticamente ottimizzazioni simili , puoi spesso evitare questo lavoro e lasciare la query in una forma più comprensibile e gestibile. Di seguito alcune delle ottimizzazioni eseguite da MySQL:

  • ...

  • Per ogni tabella in un join, viene costruito un WHERE più semplice per ottenere una rapida valutazione WHERE per la tabella e anche per saltare le righe il più presto possibile .

  • Ogni indice di tabella viene interrogato, e viene utilizzato l'indice migliore a meno che l'ottimizzatore ritenga che sia più efficiente da utilizzare una scansione della tabella . Una volta, è stata utilizzata una scansione in base al fatto che l'indice migliore si estendesse oltre il 30% della tabella, ma una percentuale fissa non determina più la scelta tra l'utilizzo di un indice o una scansione. L'ottimizzatore ora è più complesso e basa la sua stima su fattori aggiuntivi come la dimensione della tabella, il numero di righe e la dimensione del blocco I/O.

In questo modo è razionale per Query Optimizer omettere l'ordine HOW abbiamo usato le colonne nella query (non solo MySQL ma SQL è un linguaggio dichiarativo e dobbiamo fare ciò che vogliamo, non come vogliamo).

Tuttavia, adoro ancora avere lo stesso tipo per le colonne di una chiave composita nella query, ma a volte è inevitabile, ad esempio, quando utilizziamo ORM o ActiveRecord, in alcuni framework come yii2, la personalizzazione dei criteri di relazione verrà aggiunta alla fine di una condizione "on", ma abbiamo ancora bisogno delle capacità di QueryBuilders in diverse parti di un'applicazione.

1
Alix