views:

64

answers:

2

hi all, i have this query in a table with about 100k records, it runs quite slow (3-4s), when I take out the group it's much faster (less than 0.5s). I'm quite at loss what to do to fix this :

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 has indexes on thread_id,id, senderid and recipientid

explain returns :

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

Any ideas how to speed this up while returning the same result (there are multiple messages per thread, i want to return only one message per thread in this query).

thanks in advance.

+1  A: 

try this:

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)

Or this:

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)

Why were the user tables left joined? Can a message be missing a from or to?..

Fosco
Thanks a million, I tried both options - first option about 1.5s, second option about 2s. anything else i can do to bring it down more ?
Sherif Buzz
@Sherif well, do you really need ALL of the threads at once?... Is there a datetime column that could be used to cut down on the required data?
Fosco
@Forsco, actually this query is translated into is a select count(*) of query by a paging class - yes i need all threads as this is for an admin function...
Sherif Buzz
@Sherif so do you need the real data or just the count? Or is the result cached and then paginated?
Fosco
yes the result is cached and paginated.
Sherif Buzz
@Sherif Ok, just checking. Glad we were able to cut the time down, not sure I could do much more for you.
Fosco
A: 

The biggest problem is that you have no usable indexes on msgtable. Create an index on at least senderid and recipientid, and it should help the speed of your query, as it will limit the number of results needing to be scanned.

gms8994
I do have indexes on those, updated question above.
Sherif Buzz