Lavoriamo questo partendo con la query interiore, che is:
SELECT acctuniqueid,
MIN(radacctid) radacctid
FROM radacct
WHERE username='batman215'
and acctstarttime between '2016-02-03 12:10:47'
and '2016-04-25 16:46:01'
GROUP BY acctuniqueid
Stai cercando una corrispondenza di uguaglianza su username
e una corrispondenza di intervallo su acctstarttime
. Quindi stai utilizzando acctuniqueid
per raggruppare e estraendo un valore estremo (MIN()
) da radacctid
.
Pertanto, per accelerare questa sottoquery, è necessario il seguente indice composto.
(username, acctstarttime, acctuniqueid, radacctid)
Come funziona? Pensa a un indice (questi sono gli indici BTREE) come elenco ordinato dei valori in esso contenuti.
- Il motore di query casuale accede alla lista - veloce, O (log (n)) - per trovare la prima voce corrispondente
username
e la fascia bassa del range BETWEEN
.
- Quindi esegue la scansione in sequenza dell'elenco, voce per voce, fino a raggiungere la fascia alta dell'intervallo
BETWEEN
. Questa è chiamata scansione dell'indice .
- Mentre esegue la scansione, cerca ogni nuovo valore di
acctuniqueid,
in ordine e quindi prende il valore più basso - il primo in ordine - di radacctid
, quindi salta al valore successivo di accuniqueid
.Si chiama indice indice allentato ed è miracolosamente economico.
Quindi, aggiungere quell'indice composto. Questo probabilmente farà una grande differenza per le prestazioni della tua query.
La query esterna è simile a questa.
SELECT sum(acctinputoctets) as upload,
sum(acctoutputoctets) as download
FROM radacct a
INNER JOIN ( /*an aggregate
* yielding acctuniqueid and raddactid
* naturally ordered on those two columns
*/
) b ON a.acctuniqueid = b.acctuniqueid
AND a.radacctid = b.radacctid
per questo è necessario il composto di copertura dell'indice
(acctuniqueid, radacctid, acctinputoctets, acctoutputoctets)
Questa parte della query è soddisfatto con la magia indice.
- Le prime due colonne dell'indice consentono la ricerca di ciascuna riga necessaria, in base al risultato della query interna.
- Il motore di query può quindi eseguire la scansione dell'indice sommando i valori delle altre due colonne.
(questo è chiamato un copre indice perché contiene alcune colonne che sono presenti solo perché vogliamo che i loro valori, non perché vogliamo loro indicizzati. Alcuni altri marche e modelli di DBMS permettono colonne aggiuntive da inserire negli indici senza renderli ricercabili.Questo è un po 'più economico, specialmente sulle operazioni INSERT
. MySQL non lo fa.)
Quindi, il tuo primo elemento di azione: aggiungi questi due indici composti e riprova la query.
Sembra, dalla tua domanda, che hai inserito molti indici a colonna singola sul tuo tavolo nella speranza che accelerino le cose. Questo è un famigerato antipattern nella progettazione di database. Con rispetto, dovresti sbarazzarti di tutti gli indici che non conosci di cui hai bisogno. Non aiutano le query e rallentano INSERTS
. Questo è il tuo secondo oggetto d'azione.
In terzo luogo, leggi questo http://use-the-index-luke.com/ È molto utile.
Suggerimento per professionisti: hai visto come ho formattato la query? Sviluppare una convenzione di formattazione personale che mostri chiaramente tabelle, colonne, condizioni ON
e altri aspetti di una query è estremamente importante quando devi comprenderne una.
Mostrate quali sono i vostri indici e potete gentilmente postare l'output di spiegare orizzontalmente (più facile da confrontare) – e4c5
mostrare anche il vostro indice. –
Si potrebbe provare ad aggiungere un indice multi colonna sul nome utente e sui campi acctstarttime. – Shadow