2012-12-16 11 views
5

devo un esempio di query come ad esempio:Quale tipo di indice è ideale per questa query?

SELECT 
    rest.name, rest.shortname 
FROM 
    restaurant AS rest 
    INNER JOIN specials ON rest.id=specials.restaurantid 
WHERE 
    specials.dateend >= CURDATE() 
AND 
    rest.state='VIC' 
AND 
    rest.status = 1 
AND 
    specials.status = 1 
ORDER BY 
    rest.name ASC; 

Chiedo solo di sotto dei due indici, che sarebbe meglio sul tavolo del ristorante?

id,state,status,name 
state,status,name 

Non è sicuro che la colonna utilizzata nel join debba essere inclusa?

abbastanza

Divertente però, mi hanno creato entrambi i tipi per i test ed entrambe le volte MySQL sceglie l'indice primario, che è solo id. Perché?

Spiegate in uscita:

1,'SIMPLE','specials','index','NewIndex1\,NewIndex2\,NewIndex3\,NewIndex4','NewIndex4','11',\N,82,'Using where; Using index; Using temporary; Using filesort', 
1,'SIMPLE','rest','eq_ref','PRIMARY\,search\,status\,state\,NewIndex1\,NewIndex2\,id-suburb\,NewIndex3\,id-status-name','PRIMARY','4','db_name.specials.restaurantid',1,'Using where' 

Non molte righe in questo momento così forse è per questo che è la scelta PRIMARIO !?

+0

È sempre possibile utilizzare 'EXPLAIN ' per ottenere alcune informazioni su come verrà eseguita la query di selezione. http://dev.mysql.com/doc/refman/5.0/en/using-explain.html – Cyclonecode

+0

L'ho fatto, è così che ho scoperto che stava usando l'indice 'PRIMARY', che conteneva la colonna' id'. – Brett

+0

Potresti postare il tuo output completo di spiegazioni e la versione di MySQL? –

risposta

2

Per ottenere prestazioni ottimali, è necessario almeno 2 indici:

L'indice più importante è quello sulla chiave esterna:

CREATE INDEX specials_rest_fk ON specials(restaurantid); 

Senza questo, le vostre domande saranno effettuare male, perché ogni riga in rest che corrisponde alle condizioni WHERE richiederà un tablescan completo di specials.

Il prossimo indice da definire sarebbe quello che consente di cercare le meno righe di rest in base alle condizioni. Viene sempre utilizzato un solo indice, quindi si desidera che l'indice trovi il numero minimo di righe da rest possibile.

La mia ipotesi, lo stato e la condizione:

CREATE INDEX rest_index_1 on rest(state, status); 

Il tuo indice di suggerimento di (id, ...) è inutile, perché id è unico - l'aggiunta più colonna non aiuterà, e di fatto peggiorerebbe prestazioni se fosse usato, perché le voci dell'indice sarebbero più grandi e otterresti meno voci per pagina I/O letti.

Ma è possibile ottenere prestazioni anche scrivendo meglio la query; se si trasferiscono le condizioni sugli speciali nella condizione ON di join, si otterranno prestazioni significative, poiché le condizioni di join vengono valutate quando viene eseguito il join, ma dove le condizioni vengono valutate su tutte le righe unite, ovvero il set di risultati temporaneo filtrato da la clausola WHERE è molto più grande e quindi più lenta.

modificare la tua ricerca a questo:

SELECT rest.name, rest.shortname 
FROM restaurant AS rest 
INNER JOIN specials 
    ON rest.id=specials.restaurantid 
    AND specials.dateend >= CURDATE() 
    AND specials.status = 1 
WHERE rest.state='VIC' 
AND rest.status = 1 
ORDER BY rest.name; 

Si noti come le condizioni speciali sono ora nella clausola ON.

+0

Sì, ho già creato un indice sul 'restaurantid' nella tabella delle offerte speciali. – Brett

+0

Vedi risposta modificata – Bohemian

+0

Grazie mille per quello! Non sapevo che potresti farlo con JOIN. Domande di coppia però - con l'indice che hai creato su 'rest'; non sta aggiungendo lo 'status' inutile dato che la cardinalità è così bassa? ... o non aggiungerebbe il 'nome' alla fine dell'aiuto e visto che è in' ORDER BY'? – Brett

Problemi correlati