2009-08-14 16 views
15

Sto provando a mettere a punto il mio server MySQL in modo da controllare le mie impostazioni, analizzare il registro delle query lente e, se possibile, semplificare le mie query.Indici MySQL: quanti sono sufficienti?

A volte è sufficiente se sto indicizzando correttamente, a volte no. Ho letto da qualche parte (correggimi se è una stupidità) che più indici di quanti ne ho bisogno fanno lo stesso effetto, come se non avessi nessuno degli indici.

Quanti indici sono sufficienti? Puoi dire che dipende da centinaia di fattori, ma sono curioso di sapere come posso pulire il mio mysql-slow.log quanto basta per ridurre il carico del server.

Inoltre, ho visto alcune voci di registro "interessanti" come questo:

# Query_time: 0 Lock_time: 0 Rows_sent: 22 Rows_examined: 44 
SELECT * FROM `categories` ORDER BY `orderid` ASC; 

La tabella in questione contiene esattamente 22 righe, indice impostato in orderid. Perché questa query viene visualizzata nel registro dopo tutto? Perché esaminare 44 righe se contiene solo 22?

+0

Immagino che faccia una specie, quindi in qualche modo esamina la stessa riga più volte: x – Lliane

+0

Cosa viene restituito per EXPLAIN SELECT * FROM 'categories' ORDER BY' orderid' ASC; – Powerlord

+0

@R. Bemrose: Se correggo, restituisce un Extra: Usando filesort. Forse questo è il problema? – fabrik

risposta

22

La quantità di indicizzazione e la linea di fare troppo dipenderanno da molti fattori. Su tavoli piccoli come la tua tabella "categorie" di solito non vuoi o hai bisogno di un indice e questo può davvero danneggiare le prestazioni. Il motivo è che richiede I/O (cioè tempo) per leggere un indice e quindi più I/O e il tempo per recuperare i record associati alle righe corrispondenti. Un'eccezione è quando si interrogano solo le colonne contenute all'interno dell'indice.

Nell'esempio si recuperano tutte le colonne e solo con 22 righe e potrebbe essere più veloce eseguire semplicemente una scansione della tabella e ordinare quelle invece di utilizzare l'indice. L'ottimizzatore potrebbe/dovrebbe fare questo e ignorare l'indice. Se questo è il caso, allora l'indice sta semplicemente occupando spazio senza alcun beneficio. Se si accede spesso alla tabella "categorie", è consigliabile prendere in considerazione la possibilità di bloccarla in memoria, in modo che il server db la renda accessibile senza dover accedere continuamente al disco.

Quando si aggiungono gli indici, è necessario bilanciare lo spazio su disco, le prestazioni delle query e le prestazioni di aggiornamento e inserimento nelle tabelle. È possibile ottenere più indici su tabelle statiche e che non cambiano molto rispetto alle tabelle con milioni di aggiornamenti al giorno. Inizierai a sentire gli effetti della manutenzione dell'indice a quel punto. Ciò che è accettabile nel tuo ambiente è e può essere determinato solo da te e dalla tua organizzazione.

Quando si esegue l'analisi, assicurarsi di generare/aggiornare la tabella e le statistiche dell'indice in modo da poter essere certi di calcoli accurati.

+0

Grazie! Questa è stata la risposta più chiara e utile per me! – fabrik

+0

Come si "incolla" un tavolo in memoria? –

+0

Come posso dire a MySQL di "appuntare" un tavolo in memoria? – satoru

3

Non esiste un numero magico per il "migliore" numero di indici. La regola di base è questa: aggiungere indici per le query che vengono utilizzate spesso e/o che devono essere eseguite rapidamente.

Avere indici "troppi" non dovrebbe rallentare le query, ma ogni indice aggiunto aggiunge una piccola quantità di tempo per aggiungere/aggiornare elementi nel db (poiché modifica anche gli indici) e una piccola quantità di spazio. Tuttavia, se stai solo aggiungendo indici come richiesto, probabilmente non è una grande preoccupazione.

13

Come regola generale, si dovrebbero avere indici su tutte le chiavi primarie (non si ha scelta in questo), tutte le chiavi esterne e qualsiasi altro campo che si usa comunemente per recuperare le righe.

Ad esempio, se di solito cerco gli utenti per nome utente, l'indicizzo, anche se l'ID utente era la chiave primaria.

6

Quanti indici dipendono interamente dalle query in esecuzione, dal tipo di join effettuati (se presenti), dal tipo di dati memorizzati nella tabella e dalla grandezza delle tabelle (nonché da molti altri fattori). Non c'è davvero nessuna scienza esatta. Il più grande strumento nel tuo arsenale per capire come ottimizzare una query è explain. Usando spiega puoi scoprire quale tipo di join sono stati disattivati, quali chiavi possibili potrebbero essere utilizzate e quale chiave (se presente) è stata utilizzata e quante righe sono state esaminate per ogni tabella nel join.

Utilizzando queste informazioni è possibile decidere come modificare le tabelle e/o modificare le query per renderle più efficienti. La sintassi per spiegare è molto semplice.

EXPLAIN SELECT * FROM `categories` ORDER BY `orderid` ASC; 

nota, spiegare non realtà non eseguire la query. Quindi, se stai usando questo per eseguire il debug di una query che richiede 5 minuti per essere eseguito, spiegare sarà comunque molto veloce.

È necessario fare attenzione quando si aggiungono gli indici, poiché in tal caso gli inserti e gli aggiornamenti diventano più lenti e su tabelle molto grandi questo impatto sulle prestazioni può diventare notevole. Soprattutto se la stessa tabella viene utilizzata per molte letture. Generalmente l'aggiunta di un sacco di indici non uccide le prestazioni di una query, ma dovresti aggiungerli come yo

+0

Ottimo commento, grazie! – fabrik

4

Un indice può velocizzare una query SELECT, ma rallenterà le query INSERT/UPDATE/DELETE perché hanno bisogno di aggiornare anche l'indice, non solo la riga.

Questa è solo un'opinione personale (non ho fatti per eseguire il backup), ma penso che se c'è una query che impiega molto tempo e un indice lo velocizzerebbe, provaci! "Troppi" indici sarebbero se si aggiungessero indici che non funzionassero (ad esempio non ci fossero query che avrebbero accelerato). Ad esempio, una cosa stupida da fare sarebbe quella di posizionare un indice su ogni colonna "solo perché".

+0

"una cosa stupida da fare sarebbe quella di posizionare un indice su ogni colonna" solo perché "" - Questo è assolutamente ok ma mi piacerebbe eliminare quante più voci di registro lento che posso. Altrimenti, grazie per i pensieri su INSERT/UPDATE/DELETE! – fabrik

5

Inoltre, MySQL utilizzerà un massimo di un indice per selezionare l'istruzione (anche se si sta utilizzando un join, è possibile utilizzarne uno per ogni join). Quindi indicizzare solo perché è uno spreco di spazio su disco e rallenterà il database in fase di scrittura. Se usi comunemente un'istruzione where su due colonne, fai un indice contenente entrambe le colonne, sarà molto più veloce dell'indicizzazione di una sola.