2013-02-21 11 views
5

Ho una tabella semplice ->Utilizzando nella clausola() con conseguente FileSort

id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY 
by_id INT UNSIGNED NOT NULL 
posted_on INT UNSIGNED NOT NULL 

mio motore tavolo è MyISAM.

Ho un indice di colonna multipla chiamata combo1 su by_id,posted_on,id

ho funzionare questa domanda ->

EXPLAIN SELECT * FROM books 
     WHERE by_id = '1' AND posted_on = '0' 
     ORDER BY id DESC LIMIT 7; 

La colonna Extra dice Using where e colonna chiave dice combo1

Ma, quando ho eseguito questa domanda ->

EXPLAIN SELECT * FROM books 
     WHERE by_id IN(1,7,10) AND posted_on = '0' 
     ORDER BY id DESC LIMIT 7; 

La colonna Extra dice Using where; Using filesort e la colonna chiave dice combo1.

Perché nel secondo caso si verifica un filesort anche se il QEP mostra che l'ottimizzatore utilizza l'indice combo1 che ha l''id' indicizzato al suo interno.

risposta

6

L'indice è un albero B +. Ciò significa che sotto il by_id 1 ci sono tutti i record con posted_on 0 e by_id 1, e quindi hai tutti gli id ​​per quei record. Sotto il by_id 7 tuttavia hai un altro ramo di un albero, che contiene record con postato_on 0 e contengono i record con i loro id.

Quando hai in clausola, stai recuperando 3 diversi rami dell'albero, devi unirli e ricorrere loro, poiché gli id ​​con 1,2,4 possono essere sotto by_id 1, ma 3,5 sotto by_id 10 ; MySQL recupera 1,2,4,3,5 e deve ricorrere a loro.

Nel primo caso c'è solo un ramo, e ogni ramo è già ordinato

+0

Grazie grande spiegazione @Darhazer – sanchitkhanna26

+0

informi se devo togliere 'id' dall'indice combo1 .. @Darhazer – sanchitkhanna26

+0

Beh, io Non sono sicuro che MySQL sfrutti che i rami siano già ordinati e applichi merge_sort o no; forse dipende anche dalla versione. Senza un corretto benchmark, conserverei l'id nell'indice. D'altra parte, se la tabella era InnoDB, l'id è incluso alla fine di ogni indice secondario. Questo è preso in considerazione nell'ordinamento solo in MySQL 5.6, se ricordo bene. –