Newsgroup: it.comp.software.database
Titolo: [MySQL] Ottimizzazione Query

Ciao a tutti.
Ho una query di questo tipo:
SELECT (COUNT( 
S_LOG.ID
 ) / COUNT( DISTINCT SESS_LOG.SESSION_ID)) AS CNT
FROM stat_log S_LOG
      INNER JOIN stat_session_log SESS_LOG ON SESS_LOG.LOG_ID=
S_LOG.ID
WHERE S_LOG.STAMP BETWEEN '2009-06-30 22:00:00' AND '2009-07-31 21:59:59'
che ï¿œ molto lenta (15 secondi o piï¿œ).
Facendo un EXPLAIN mi viene riportato che la tabella SESS_LOG ha come
chiave possibile "LOG_ID" ma esso non viene utilizzato, infatti il campo
"Key" riportato da EXPLAN ï¿œ null.
Sapete dirmi come poter risolvere questa cosa?
Ho anche una seconda query, molto lenta, il cui risultato ï¿œ analogo.
E' troppo complessa per poter essere scritta sul newsgroup ma l'explain
mi mostra che una delle tabelle soggette a join non utilizza indice
(nonostante ci sia un LOG_ID disponibile) ed il campo "Extra" mi indica:
"Using temporary, Using filesort".
Qualche idea su come sistemare questa query?
(se facessi una vista anzichï¿œ una query ogni volta, avrei un 
miglioramento prestazionale?)

 miglioramento prestazionale?)
Ce l'hai un indice su S_LOG.STAMP ?

 Ce l'hai un indice su S_LOG.STAMP ?
si..

 si..
Se non ï¿œ un problema, fanne uno su S_LOG.STAMP,
S_LOG.ID
 (intendo un 
indice sui due campi), credo che il motore lo utilizzerï¿œ, ma il 
risultato dipende molto dal contenuto per cui non sono sicuro del 
beneficio. Al limite fai un drop.

 beneficio. Al limite fai un drop.
Mi sa che hai fatto confusione con i nomi dei campi.
Il problema ï¿œ che ï¿œ una join, non posso fare un indice
tra due campi di due tabelle differenti.
SESS_LOG.LOG_ID
S_LOG.ID
Io prendo i dati di una tabella, li unisco ai dati di una seconda
e filtro in base alla data presente sulla seconda tabella.
Il problema ï¿œ che ogni tabella ha circa 1m di record che devo
'unire' in modo da poter filtrare per data.

 
Ti assicuro che nella query che hai postato c'ï¿œ scritto (copio e 
incollo) "COUNT( 
S_LOG.ID
 )."
La ragione per farlo ï¿œ che, forse, il motore del db userï¿œ il nuovo 
indice per la parte where e la parte count. Purtroppo non ne sono certo.

 indice per la parte where e la parte count. Purtroppo non ne sono certo.
Allora:
Query:
SELECT (COUNT( 
S_LOG.ID
 ) / COUNT( DISTINCT SESS_LOG.SESSION_ID)) AS CNT
FROM stat_log S_LOG
      INNER JOIN stat_session_log SESS_LOG ON SESS_LOG.LOG_ID=
S_LOG.ID
WHERE S_LOG.STAMP BETWEEN '2009-06-30 22:00:00' AND '2009-07-31 21:59:59'
L'explain mi dice che della prima tabella (SESS_LOG) potrebbe usare la
chiave LOG_ID ma non la usa.
Nella seconda tabella (S_LOG) potrebbe usare sia STAMP che la PRIMARY
ed usa la PRIMARY.
Perï¿œ: perchï¿œ nella prima tabella non usa un indice? Quanto-meno per
fare la join. Io credo che attualmente MySQL stia filtrando per data
tramite la chiave e poi 'unendo' i risultati uno per uno senza indice.

 tramite la chiave e poi 'unendo' i risultati uno per uno senza indice.
Perchï¿œ se sono indici distinti non ï¿œ per nulla banale usarli assieme da 
parte del motore: dovrebbe fare un intersezione delle tuple restituite 
da due scansioni dei due indici, se giï¿œ il primo indice riduce 
sensibilmente la cardinalitï¿œ della relazione, il secondo indice non 
dovrebbe essere piï¿œ chiamato in causa perchï¿œ troppo oneroso, ma non 
posso in alcun modo essere certo di quello che dico. Per questo motivo 
ti ho suggerito caldamente di fare un unico indice su due campi e 
provare l'effetto che fa.

 provare l'effetto che fa.
Urca, ho creato l'indice e sembra usarlo.
Se faccio EXPLAIN ora mi indica almeno 1 indice per ogni tabella
e mi dice: "Using WHERE, Using INDEX".
Ora impiega 6 secondi anzichï¿œ 15.
Mi sa che sotto questi 6 secondi non posso proprio andare, considerato
che sono due tabelle da circa 1 milione di record ciascuna...
Ho pensato persino di partizionare in 365 pezzi (1 per ogni giorno
dell'anno, dato che nella query ho sempre un filtro per giorno) ma
MySQL 5.0 che non posso upgradare non supporta le partizioni.

 prestazionale?)
Solo in caso di viste materializzate. Le viste "ordinarie"
non sono altro che etichette che vengono espanse dal parser
nella corrispondente definizione.