Dzisiaj walczyłem z dość prostym, aczkolwiek powolnym zapytaniem SQL. Problem pewnie polegał na tym, że dane były pobierane z tabeli o ~50k rekordach, sortowane, grupowane itd.
Owe zapytanie wyglądało mniej więcej tak:
SELECT *, CONCAT(firstname ,' ', lastname) as fullname FROM users GROUP BY fullname ORDER BY lastname ASC LIMIT 0, 10;
Co ciekawe to zapytanie było strasznie powolne – czas wykonania 1,7s. Dodatkowo zapytanie EXPLAIN dobiło faktem, że zapytanie typu SIMPLE musi wykorzystywać tabele tymczasową.
Aby całość przyspieszyć założono indeks na pola firstname i lastname
ALTER TABLE users ADD INDEX `firstname-lastname` (`firstname`, `lastname`)
Oraz odpowiednio zmodyfikowaliśmy zapytanie:
SELECT *, CONCAT(firstname ,' ', lastname) as fullname FROM users GROUP BY firstname, lastname ORDER BY firstname, lastname ASC LIMIT 0, 10;
Całość działała poprawnie i, co najważniejsze, szybko. Okazało się, że zapytanie ma jedną wadę. Sortowanie ma być najpierw po polu lastname, a potem po polu firstname. Okazuje się, że prosta zamiana kolejnością pól w wyrażeniu ORDER BY skutkuje spowolnieniem czasu wykonywania.
Fakt, czy będziemy grupować najpierw po polu firstname, a później po polu lastname nie miał znaczenia, dlatego postanowiono na zamianę kolejności tych pól, oraz poprawienie indeksu.
ALTER TABLE users DROP INDEX `firstname-lastname`, ADD INDEX `lastname-firstname` (`lastname`, `firstname`)
Dodatkowo drobna zmiana zapytania na:
SELECT *, CONCAT(firstname ,' ', lastname) as fullname FROM users GROUP BY lastname, firstname ORDER BY lastname, firstname ASC LIMIT 0, 10;
I całość śmiga, aż miło :)
Okazuje się, że dla serwera MySQL kolejność pól w zakładanym indeksie ma wpływ na późniejszy czas wykonywania zapytań.
2 Komentarze
Hi
>>Całość działała poprawnie i, co najważniejsze, szybko. Okazało się, że zapytanie ma jedną wadę.
>>Sortowanie ma być najpierw po polu lastname, a potem po polu firstname. Okazuje się, że prosta
>>zamiana kolejnością pól w wyrażeniu ORDER BY skutkuje spowolnieniem czasu wykonywania.
Zachowanie mysql bylo jak najbardziej przewidywalne. Czego mi brakuje w tym poscie to wyjasnienia dlaczego cos dziala lub nie dziala.
Jesli masz index (col1, col2) i robisz GROUP BY col1,col2 to automatycznie mysql robi
GROUP BY col1,col2 ORDER BY col1 ASC, col2 ASC wiec twoje zapytanie z
GROUP BY firstname, lastname
ORDER BY firstname, lastname ASC
nie powoduje wykonania zadnego nowego sortowania. Po prostu dopisales cos co juz zostalo dopisane nie wprost. Jesli nie chcesz, by grupowanie robilo automatycznie ORDER BY wyraznie to sygnalizujesz przez ORDER BY NULL.
>>Okazuje się, że dla serwera MySQL kolejność pól w zakładanym indeksie ma wpływ na późniejszy
>>czas wykonywania zapytań.
sluszna uwaga :-D Mysle, ze czesciej powinienes zagladac do
http://dev.mysql.com/doc/refman/5.1/en/index.html
http://www.mysqlperformanceblog.com/
polecam rowniez wiedze w pigulce czyli 2-3 rozdzialy (tj. Benchmarking, Indexes, Query Optimization) z “High Performance MySQL” By Jeremy Zawodny, Derek J. Balling
Pozdrawiam,
Marcin
Ano racja. mysqlperformanceblog właśnie dodałem do subskrypcji, a co do manuala to odwieczna prawda, choć nie zawsze jest na to czas :)