2009-09-09 27 views
6

ATM Sto cercando di imparare come utilizzare in modo efficiente i database inidici e vorrei avere qualche input da esperti. Al momento non ho problemi di prestazioni. Vorrei solo sapere, come si dovrebbe gestire i vostri indici con questa query:Come velocizzare questa query?

SELECT B.event, 
     COALESCE(B.system, C.surname || ' ' || C.forename) AS name, 
     C.label, 
     B.timestamp 
FROM A    
    INNER JOIN B ON A.event=B.event 
    INNER JOIN C ON B.state=C.id 
    LEFT OUTER JOIN D ON B.hur=D.id    
WHERE A.id IN(12,13,14,15,...) 
    ORDER BY B.event, B.timestamp 

A.id, C.id e D.id sono già le chiavi primarie

UPDATE Normalmente avrei messo INDEX (A.event) e INDICE (B.event, B.timestamp). È corretto? E che dire di B.event, B.state e B.hur?

+0

Correggere, ma controllare se B.timestamp verrebbe effettivamente utilizzato. – Pomyk

+0

Quanto sono grandi ciascuna tabella e quante righe ci si aspetterebbe che corrispondano da una determinata query. Quale database stai usando? –

+0

Inoltre, con quale frequenza vengono aggiunti i dati nelle tabelle e con quale frequenza si desidera eseguire la query? –

risposta

3

riscrivere la query come questa:

SELECT B.event, 
     COALESCE(B.system, C.surname || ' ' || C.forename) AS name, 
     C.label, 
     B.timestamp 
FROM B    
INNER JOIN 
     C 
ON  C.id = B.state 
LEFT OUTER JOIN 
     D 
ON  D.id = B.hur 
WHERE B.event IN 
     (
     SELECT event 
     FROM A 
     WHERE A.id IN (12, 13, 14, 15) 
     ) 
ORDER BY 
     B.event, B.timestamp 

, e creare un indice composito sulla B (event, timestamp)

2

È possibile aggiungere indici a tutto nelle clausole WHERE e ORDER BY. Iev A.event, B.event e B.timestamp.

+1

Non aggiungere indici ciecamente. Vedi la risposta di Lieven. Aggiungere indici ciecamente può danneggiare le prestazioni in quanto ogni indice deve essere mantenuto. In alcuni casi, come le tabelle di piccole dimensioni, ciò si ripercuote sul fatto che l'IO utilizzato per la manutenzione potrebbe essere utilizzato altrove. A volte una scansione completa della tabella su un piccolo tavolo è meglio degli indici. – jim

+0

Sono tentato di cancellare la mia risposta; tuttavia, il commento di jim è un'informazione utile, quindi la risposta dovrebbe essere lasciata? – darasd

0
SELECT B.event, B.system, COALESCE(C.surname) || ' ' || COALESCE(C.forename) AS name, C.label, B.timestamp 
FROM A    
INNER JOIN B ON A.event=B.event 
INNER JOIN C ON B.state=C.id 
LEFT OUTER JOIN D ON B.hur=D.id    
WHERE A.event = ANY(:visits) 
ORDER BY B.event, B.timestamp 

Anche l'ordine BY rallenterà gravemente le cose. assicurarsi che questi sono indicizzati:

A.event 
B.event 
B.state 
C.id 
B.timestamp 
3

solito prendo questi passaggi quando si cerca di accelerare le mie domande

  1. analizzare il piano di esecuzione.
  2. tenta di creare indici (di copertura) per eliminare scansioni di tabelle.
  3. tenta di creare indici (di copertura) per eliminare le scansioni dell'indice.

Per quanto riguarda la si esegue una query, non sarebbe andare male con gli indici che creano sul

  • A.event
  • B.event
  • B.state
  • B.Hur
+0

La creazione di indici separati per B.event e B.state non equivale alla creazione di un indice su (B.event, B.state). È importante differenziarlo poiché ha un impatto diretto sulle prestazioni. – MatBailie

+0

@Dems: se ciò non è stato chiarito nella mia risposta, hai ragione. –

1

Aggiungerei indici a tutto ciò che è unito, nella clausola where o nella clausola order by.

In questo caso aggiungere indici dei seguenti (campi ID supponendo sono chiavi primarie e già indicizzati):

  1. A.event
  2. B.event
  3. B.state
  4. B. hur
  5. B.event, B.timestamp (combinato indice di entrambi i campi)

Il 5 °, essendo una combinazione di indici dovrebbe velocizzare l'ordine di.

È necessario moderare il numero di indici, rispetto a qualsiasi calo di prestazioni che si ha nell'inserimento di record nella tabella (più indici si aggiungono alla tabella, gli inserimenti e gli aggiornamenti più lenti saranno, come gli indici devono essere aggiornati) .

2

E 'importante notare che l'ordine dei campi nell'indice è importante.

Un indice è, in un certo senso, un albero di ricerca. Se indicizzi (B.event, B.state), l'albero raggrupperà tutti i record con il campo "evento" di salvataggio, quindi li ordinerà con il campo "stato".

Se si dovesse interrogare quell'indice per "b.state = x", l'indice sarebbe di scarsa utilità; L'indice è ordinato prima dall'evento.


Nel tuo esempio:
- Un filtro da esso è "evento" campo
- unire A.event a B.event
- unire B.state a C.id
- Join B.hur = D.id
- Ordina per B.event, B.timestamp

e 'importante notare che l'ottimizzare esaminerà le statistiche delle vostre tabelle e indici, quindi può ri-organizzare l'ordine di i join Il risultato sarà lo stesso, ma l'ordine potrebbe dare prestazioni diverse e il lavoro degli ottimizzatori è cercare di trovare le migliori prestazioni.

Nel tuo caso, mi aspetto che l'ordine di B.event sia estremamente importante. Semplicemente perché questo è l'ordine dell'output risultante, ed è il campo da cui filtra.

Successivamente si entra in B.state in C.id. Quindi avere e indicizzare su C.id è buono, rende il join più veloce. Ma ugualmente, avere i dati della tabella B in un buon ordine può anche rendere il join più veloce.

Tuttavia, avere un indice su B.event e un indice separato su B.state può dare poco. L'indice B.state diventa quasi inutile perché stiamo usando l'indice B.event. Se si combinano i due in un indice (b.event poi b.state) il piano di esecuzione potrebbe trovare un modo per utilizzare la parte b.state dell'indice.

Infine, se si inseriscono tutti i campi nell'indice, l'indice diventa più grande, ma la query potrebbe non avere mai realmente bisogno di guardare la tabella. Le informazioni sono nell'indice. Il tempo impiegato per passare da un indice alla tabella per trovare i campi "mancanti" è simile a quello di un join. Pertanto, per le prestazioni di lettura, l'aggiunta di campi aggiuntivi all'indice può essere di notevole utilità.

sto Wittering adesso, ma la sintesi è questa:
- Di solito, indice separato su campi separati non abituarsi insieme
- Per gli indici compositi, nell'ordine specificato i campi fa la differenza
- L'aggiunta di campi "extra" all'indice lo rende più grande, ma può anche velocizzare le query
- L'ordine del piano di esecuzione è più importante dell'ordine della query
- Ma gli indici che hai possono determinare l'ordine di il piano di esecuzione

Questo tipo di lavoro ha nessuna risposta categoriale. È così dipendente dai tuoi dati che è più vicino a un'arte.

Un'opzione consiste nel caricare le tabelle con gli indici, osservare il piano di esecuzione risultante ed eliminare gli indici non necessari.

Ma anche qui si applica un avvertimento. Poiché il piano di esecuzione dipende dai dati (e dalle statistiche delle tabelle), è molto importante avere dati del mondo reale nelle tabelle. Mentre le tabelle hanno 10 o 100 di righe, un piano di esecuzione potrebbe essere il più veloce. Ma quando ottieni milioni di righe, il piano di esecuzione può cambiare e beneficiare quindi di diversi indici.

2

Esegui spiegare l'analisi della query e leggerla, se non aiuta, inserire l'output di analisi spiegare su explain.depesz.com e verificare cosa "dice".