2010-10-26 3 views
5

У меня есть этот запрос в таблице с около 100 тыс. Записей, он работает довольно медленно (3-4 секунды), когда я вынимаю группу намного быстрее (меньше 0,5 с). Я совершенно в недоумении, что делать, чтобы исправить это:mysql "group by" очень медленный запрос

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 имеет индексы thread_id, id, senderid и recipientid.

объяснить возвращается:

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 

Любые идеи, как ускорить этот процесс, а возвращаясь в тот же результат (есть несколько сообщений в теме, я хочу вернуть только одно сообщение на поток в этом запросе).

благодарит заранее.

+1

Как насчет индексов 'usertable'? Можете ли вы запустить «EXPLAIN » и опубликовать результаты? – Frankie

+1

Как правило, вам необходимо объявить все столбцы, упомянутые в SELECT, которые не инкапсулированы агрегатными функциями (COUNT, SUM, MIN, MAX и т. Д.) В GROUP BY. Будет ли «DISTINCT» служить вам лучше в этой ситуации? –

+0

Почему левые присоединяются? Не будет ли каждое сообщение требовать получателя и отправителя? –

ответ

1

попробовать это:

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) 

Или это:

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) 

Почему таблицы пользователь оставил присоединился? Может ли сообщение отсутствовать от или до? ..

+0

Спасибо, миллион, я попробовал оба варианта - первый вариант около 1,5 секунд, второй вариант около 2 секунд. что-нибудь еще, что я могу сделать, чтобы снизить его? –

+0

@Sherif хорошо, вам действительно нужно ВСЕ из потоков сразу? ... Есть ли столбец datetime, который можно использовать для сокращения требуемых данных? – Fosco

+0

@Forsco, на самом деле этот запрос переводится в select count (*) запроса пейджинговым классом - да, мне нужны все потоки, поскольку это для функции администратора ... –

0

Самая большая проблема в том, что у вас нет полезных индексов на msgtable. Создайте индекс на как минимумsenderid и recipientid, и это должно помочь ускорить ваш запрос, так как это ограничит количество результатов, которые необходимо отсканировать.

+0

У меня есть указатели на те, обновленный вопрос выше. –

Смежные вопросы