2010-10-26 26 views
5

Mam to zapytanie w tabeli z około 100 tys. Rekordów, działa dość wolno (3-4s), kiedy wyjmuję grupę jest znacznie szybszy (mniej niż 0.5s). Jestem całkiem na straty, co zrobić, aby rozwiązać ten problem:mysql "group by" bardzo powolne zapytanie

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 ma indeksów thread_id, id, senderid i recipientid.

wyjaśnić Powroty:

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 

Jakieś pomysły jak to przyspieszyć wracając ten sam wynik (istnieje wiele wiadomości w wątku, chcę wrócić tylko jedną wiadomość na wątek w tym zapytaniu).

z góry dzięki.

+1

Co z indeksami 'usertable'? Czy możesz uruchomić 'EXPLAIN ' i opublikować wyniki? – Frankie

+1

Zazwyczaj należy zadeklarować wszystkie kolumny wymienione w SELECT, które nie są enkapsulowane przez funkcje agregujące (COUNT, SUM, MIN, MAX, itd.) W GROUP BY. Czy "DISTINCT" lepiej Ci służy w tej sytuacji? –

+0

Dlaczego lewy dołączyć? Czy każda wiadomość nie wymaga odbiorcy i nadawcy? –

Odpowiedz

1

spróbuj tego:

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) 

Albo to:

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) 

Dlaczego tabele użytkownik opuścił dołączył? Czy w komunikacie może brakować lub odbierać? ..

+0

Dzięki milionowi spróbowałem obu opcji - pierwsza opcja około 1,5 s, druga opcja około 2s. cokolwiek innego mogę zrobić, żeby go bardziej obniżyć? –

+0

@Sherif dobrze, czy naprawdę potrzebujesz WSZYSTKICH wątków naraz? ... Czy istnieje kolumna datetime, która mogłaby zostać wykorzystana do zmniejszenia wymaganych danych? – Fosco

+0

@Forsco, w rzeczywistości to zapytanie jest tłumaczone na to liczba wybranych zapytań (*) według klasy stronicowania - tak, potrzebuję wszystkich wątków, ponieważ jest to funkcja administratora ... –

0

Największym problemem jest brak użytecznych indeksów na msgtable. Utwórz indeks na co najmniej i recipientid, a to powinno pomóc w szybszym wyszukiwaniu, ponieważ ograniczy liczbę wyników wymagających skanowania.

+0

Mam indeksy tych, zaktualizowane pytanie powyżej. –