2010-10-26 18 views
5

Ho questa query in una tabella con circa 100k di record, viene eseguito piuttosto lento (3-4s), quando estrapolo il gruppo è molto più veloce (meno di 0,5 s). Sono abbastanza a perdita di cosa fare per risolvere questo problema:mysql "group by" query molto lenta

SELECT msg.id, 
     msg.thread_id, 
     msg.senderid, 
     msg.recipientid, 
     from_user.username AS from_name, 
     to_user.username AS to_name 
FROM msgtable AS msg 
LEFT JOIN usertable AS from_user ON msg.senderid = from_user.id 
LEFT JOIN usertabe AS to_user ON msg.recipientid = to_user.id 
GROUP BY msg.thread_id 
ORDER BY msg.id desc 

msgtable ha indici sulle thread_id, id, senderid e recipientid.

spiegano i rendimenti:

id select_type table type possible_keys key key_len ref rows Extra 
1 SIMPLE msg ALL NULL NULL NULL NULL 162346 Using temporary; Using filesort 
1 SIMPLE from_user eq_ref PRIMARY PRIMARY 4 db.msg.senderid 1  
1 SIMPLE to_user eq_ref PRIMARY PRIMARY 4 db.msg.recipientid 1 

Delle idee come accelerare l'operazione mentre tornava lo stesso risultato (ci sono più messaggi per discussione, voglio tornare solo messaggio per thread in questa query).

grazie in anticipo.

+1

E gli indici 'usertable'? Puoi eseguire "SPIEGA " e pubblicare i risultati? – Frankie

+1

In genere, è necessario dichiarare tutte le colonne menzionate in SELECT che non sono incapsulate da funzioni di aggregazione (COUNT, SUM, MIN, MAX, ecc.) In GROUP BY. 'DISTINCT' ti servirebbe meglio in questa situazione? –

+0

Perché la sinistra si unisce? Ogni messaggio non richiederebbe un destinatario e un mittente? –

risposta

1

provare questo:

select m.thread_id, m.id, m.senderid, m.recipientid, 
     f.username as from_name, t.username as to_name 
from msgtable m 
join usertable f on m.senderid = f.id 
join usertable t on m.recipientid = t.id 
where m.id = (select MAX(id) from msgtable where thread_id = m.thread_id) 

O questo:

select m.thread_id, m.id, m.senderid, m.recipientid, 
     (select username from usertable where id = m.senderid) as from_name, 
     (select username from usertable where id = m.recipientid) as to_name 
from msgtable m 
where m.id = (select MAX(id) from msgtable where thread_id = m.thread_id) 

Perché gli tabelle utente sinistra uniti? Può mancare un messaggio da o a? ..

+0

Grazie mille, ho provato entrambe le opzioni: prima opzione su 1.5s, seconda opzione su 2s. Qualcos'altro che posso fare per abbatterlo di più? –

+0

@Sherif bene, hai davvero bisogno di TUTTI i thread in una volta? ... C'è una colonna datetime che potrebbe essere utilizzata per ridurre i dati richiesti? – Fosco

+0

@Forsco, in realtà questa query è tradotta in un conteggio selezionato (*) di una query da una classe di paging - sì ho bisogno di tutti i thread come questo è per una funzione di amministrazione ... –

0

Il problema più grande è che non si dispone di indici utilizzabili su msgtable. Creare un indice su almenosenderid e recipientid e dovrebbe aiutare la velocità della query, poiché limiterà il numero di risultati che devono essere sottoposti a scansione.

+0

Ho indici su quelli, domanda aggiornata sopra. –