2012-03-22 12 views
13

Ho una tabella di voci 200k con colonne di INT. Voglio creare un indice per rendere le query più veloci. Questa è la query che vorrei eseguire: SELECT A,B,C,D,E FROM table WHERE A=23 and (B=45 or C=43). Ho creato i seguenti indici: B, ACD, C, ABC.MySQL. Creazione di un indice per query "OR"

Con il comando EXPLAIN ho trovato che MySQL sceglie l'indice ACD. Così ho continuato a popolare la tabella con più valori e mi sono reso conto che MySQL stava passando dagli indici sopra (non sempre lo stesso).

Poiché ci sono molti inserti, avere vari indici causerà problemi di prestazioni e possiamo presumere che questa tabella sia accessibile da altre query che richiedono colonne diverse in cui ogni indice ha senso.

Sono a conoscenza dello USE INDEX(), ma mi piacerebbe capire se dovremmo fidarci di MySQL per scegliere l'indice giusto.

+2

Cosa intendi per "possiamo supporre che questa tabella sia accessibile da altre query che richiedono colonne diverse in cui ogni INDICE ha senso"? Potresti fornire alcuni esempi di tali domande? Puoi darci anche l'output di una query 'SHOW INDEXES FROM table'? Gli indici su A, AB e AC sono sicuramente ridondanti: questi sono già coperti dagli indici su ACD/ABC, ABC e ACD rispettivamente. Puoi leggere come MySQL gestisce gli indici multi-colonna su http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html – Daan

+0

Query di esempio: 'RICEVI B DA tabella WHERE B = 12'. Ok, posso eliminare A, AB, AC (grazie). Ma non spiega ancora il motivo dell'uso di "ACD". Quando 'D' non è nemmeno nell'istruzione' WHERE'. –

+0

Sì, è un po 'misterioso: l'output di una query 'SHOW INDEXES FROM table' può aiutare a capire perché sta accadendo :) – Daan

risposta

6

A causa della OR nell'istruzione SQL, MySQL viene semplicemente ottenendo il primo indice che include A, che è ACD.

Sono giunto alla conclusione che il modo per risolvere questo problema utilizzando un INDEX consiste nel creare due query separate. SELECT A,B,C,D,E FROM table WHERE A=23 AND B=45 che utilizzerà INDEX ABC e quindi SELECT A,B,C,D,E FROM table WHERE A=23 AND C=43 che utilizzerà INDEX ACD. Tutto questo può essere fatto in un solo passaggio con (...) UNION (...), che risulta essere più veloce e utilizza solo INDICE.

1

Mysql può utilizzare solo la parte "left most" di un indice composito. Vale a dire, se la vostra clausola in cui si presenta come

WHERE A=1 AND B=2 

poi MySQL può utilizzare un indice su A o AB, ma AB sarebbe meglio. ACB non può essere utilizzato poiché l'indice è diviso da un'altra colonna

Con la clausola WHERE specificata, non penso che il motore di query MySQL possa utilizzare più indici. Vorrei creare un AB e AC e utilizzare FORCE INDEX, vedere quale è più veloce.

Una chiave composita a tre colonne non è di aiuto in questo caso poiché si sta osservando A e un'altra colonna. Questo tipo di chiave potrebbe essere utile se la query utilizzava AND anziché OR. Un indice su ABC sarebbe utile per

WHERE A=1 AND B=2 AND C=3 
+2

Sì, con 'AND' utilizza la query ABC come previsto. Usare 'A',' AB', 'AC' sarebbe ridondante come menzionato da @Daan nel commento precedente. Dalla documentazione di MySQL: "Il prefisso più a sinistra dell'indice può essere usato dall'ottimizzatore per trovare le righe.' INDICE' on (col1, col2, col3), hai indicizzato le capacità di ricerca su (col1), (col1, col2), e (col1, col2, col3). " –

+1

Questa è una domanda su OR, non AND. –