2009-07-17 8 views
7

Ho un indice composito basato su 3 colonne, due delle quali sono vincolate nella mia query e la terza è in ordine per clausola, ma mysql non usa l'indice per l'ordinamento.Ottimizzazione della mia query mysql per utilizzare l'indice per l'ordinamento

 
explain select * from videos where public_private='public' and approved='yes' order by number_of_views desc; 

+----+-------------+--------+------+--------------------------------+------+---------+------+---------+-----------------------------+ 
| id | select_type | table | type | possible_keys     | key | key_len | ref | rows | Extra  | 
+----+-------------+--------+------+--------------------------------+------+---------+------+---------+-----------------------------+ 
| 1 | SIMPLE  | videos | ALL | approved,approved_3,approved_2 | NULL | NULL | NULL | 1476818 | Using where; Using filesort | 
+----+-------------+--------+------+--------------------------------+------+---------+------+---------+-----------------------------+ 

La struttura della tabella è la seguente:

CREATE TABLE `videos` (
    `indexer` int(9) NOT NULL auto_increment, 
    `user_id` int(9) default NULL, 
    `public_private` varchar(24) default NULL, 
    `approved` varchar(24) default NULL, 
    `number_of_views` int(9) default NULL, 
    PRIMARY KEY (`indexer`), 
    KEY `approved` (`approved`,`user_id`), 
    KEY `approved_3` (`approved`,`public_private`,`indexer`), 
    KEY `approved_2` (`approved`,`public_private`,`number_of_views`), 
) ENGINE=MyISAM AUTO_INCREMENT=1969091 DEFAULT CHARSET=utf8 | 

Cosa devo fare per forza mysql da usare indice per l'ordinamento dei risultati?

risposta

13

Credo che la query avete probabilmente abbinando una grande percentuale della dati nella tabella In situazioni come questa, l'ottimizzatore MySQL spesso sceglie di eseguire una scansione della tabella e di ignorare completamente gli indici, poiché è in realtà più veloce di passare attraverso il problema della lettura aggiuntiva dell'intero indice e di utilizzarlo per individuare i dati. Quindi, in questo caso, suppongo che public_private='yes' and approved='yes' corrisponda a una buona parte del tuo tavolo. Pertanto, se MySQL salta l'indice a causa di questo, allora non è disponibile per l'ordinamento.

Se si vuole veramente in modo da utilizzare un indice, allora la soluzione sarebbe quella di utilizzare FORCE INDEX:

select * from videos FORCE INDEX (approved_2) where public_private='public' and approved='yes' order by number_of_views desc; 

Tuttavia, vorrei eseguire alcuni test per assicurarsi che quello che stai ricevendo in realtà è più veloce di cosa ha scelto di fare l'ottimizzatore MySQL. A quanto pare l'ottimizzatore does have some issues con le selezioni per l'ordine, in modo da poter assolutamente dare un colpo e vedere se si ottiene un miglioramento delle prestazioni.

+0

FORCE INDEX ha risolto il problema. La query viene eseguita molto più velocemente ora e hai ragione riguardo alla query che corrisponde a gran parte del database. –

+0

Roba buona, felice che funzionasse. – zombat

-2

L'ordine è importante nelle chiavi composite. Ho dimenticato le regole, ma provo in un ordine diverso.

-2

aggiungere un indice separato sulla colonna number_of_views e vedere se funziona quindi.

Se una chiave è una combinazione di 3 colonne, userà quella chiave particolare solo quando sta usando tutti e 3 di eseguire un'operazione

+0

N. Corretto: Se una chiave è una combinazione di 3 colonne, utilizzerà quella particolare chiave quando utilizza la prima colonna o una combinazione di prime due colonne o tutte e tre le colonne –

1

L'ordine conta in chiavi composte. Se si desidera ordinare solo number_of_views utilizzando il approved_2 chiave, Modifica:

KEY `approved_2` (`approved`,`public_private`,`number_of_views`) 

a:

KEY `approved_2` (`number_of_views`,`approved`,`public_private`) 

chiavi composite nel lavoro MySQL da sinistra a destra. Nell'esempio di cui sopra, la chiave dichiarato utilizzando number_of_views, approved, e public_private implicitamente crea indici:

  • number_of_views
  • number_of_views, approved
  • number_of_views, approved, public_private
+0

Questa soluzione priverà 'MySQL' della possibilità di filtrare i primi due campi e di ordinare il terzo. – Quassnoi

+0

Ha chiesto perché l'indice non è stato utilizzato per l'ordinamento. –

+1

L'indice che si sta suggerendo può essere utilizzato solo per l'ordinamento. L'indice proposto da '@ op' può essere usato per filtrare * e * per l'ordinamento. L'indice non può essere utilizzato per il filtraggio, ma può essere (o meno) utilizzato per l'ordinamento. – Quassnoi

0

Questo dovrebbe funzionare :

`select * from videos where approved='yes' and public_private='public' order by number_of_views desc;` 

Se non lo fa, basta creare un indice separato su number_of_views.

Questo deve funzionare.

(mysql segue sequenza sinistra-destra in fondo. Così il vostro indice su approved, public_private, number_of_views non funziona se non utilizzato in questa sequenza. Vale a dire, è possibile utilizzare tutti e tre da sinistra, 2 da sinistra o sinistra più 1 Ma non funzionerà se non usi quella più a sinistra, è l'idea.)

L'utilizzo di un indice separato potrebbe ordinare automaticamente number_of_views, questo potrebbe aiutare in order by - questo sono sicuro però.

+0

solo l'aggiunta dell'indice 'number_of_views' non risolverà il problema poiché verrà considerato quell'indice che soddisfa la condizione' where'. Nella risposta dell'OP, l'indice 'approved_2' dovrebbe essere usato e non gli indici su' approved, public_private' e su 'number_of_views' separatamente. –