За тия почти 6 години не си спомням темата да е обсъждана тука, и все някакси се остава на заден план. Ще използвам заявките, които направихме от темата с
последната задача. Променил съм имената на таблиците и полетата да са с малки букви, че заявките са трудни за четене:
DATABASE SCHEMA
INSERT INTO `points` VALUES (1,1,1,4),(2,2,1,1),(3,3,1,3),(4,1,2,0),(5,2,2,4),(6,3,2,1),(7,3,3,1),(8,2,3,5),(9,1,3,2),(10,2,4,2),(11,1,4,3),(12,3,4,0);
INSERT INTO `gamers` VALUES (1,1,'jazzman','jazz'),(2,2,'canoncho','canon'),(3,3,'Avalanche','Ava'),(4,4,'HD','HD'),(5,1,'jazzman','jazz');
Условието на задачата може да се свери в темата на задачката, тука искам да обсъдим оптимизацията на заявките. Искам да сравним тези на Jazzman и моята (заявката на канона е идентична с моята, нека да каже ако иска да я включим и нея). Те правят едно и също нещо, но по различни начини:
Заявка 1 на Джази-Бази:
g.firstname,
g.lastname,
p.gamerid,
p.scoreweek,
tot.scoreTOTAL
)
gamerid,
) AS tot
ON (tot.gamerid
= p.gamerid
)
Заявка 2 - моята:
g.firstname,
g.lastname,
g.gamerid,
(
WHERE gamerid
= g.gamerid
)
Как се оптимизира заявка? Който е бил на интервю за работа на позиция PHP Backend или нещо от сорта е чувал този въпрос (ако не сте - пропуснали сте). Са някои ще кажат, "да се изброят полетата вместо да се вземат със звездичка", други ще кажат "сложи индекс". Но как и къде да ги направя тия неща? Ами MySQL предлага командата
EXPLAIN, с чиято помощ може да получим информация какво трябва да направи query optimizer-а за да вземе информацията, която искаме. Доста информация вади командата, темата няма да ми стигне да обесня всичко, но пък и не съм го наизустил и често се налага да търся референция, ето и какво излиза за заявката на Jaza:
+------+-------------+------------+------+---------------+------+---------+------+------+--------------------------------------------------------+
| id
| select_type
| table | type | possible_keys
| key | key_len
| ref
| rows
| Extra
| +------+-------------+------------+------+---------------+------+---------+------+------+--------------------------------------------------------+
+------+-------------+------------+------+---------------+------+---------+------+------+--------------------------------------------------------+
Накратко - имаме списък от какви отделни заявки трябва да се изпълнят за да се сглоби резултата:
id - номер на заявката
select_type -
тип на заявкатаtable - името на таблицата от където се взимат редовете
type - как са join-ати таблиците
join type (ALL е най-лошия вариант - ще се прави пълно сканиране на таблицата)
possible_keys - кои индекси може да се ползват за да се открият редовете в таблицата
key - кои индекс query optimizer-а ще използва от всичките възможни от possible_keys
key_len -
http://stackoverflow.com/a/7714306/1125161rows - броя редове, които MySQL предполага че трябва да сканира за да изпълни заявката
extra - допълнителна информация как MySQL ще обработи заявката -
обяснение на стойноститеНека да разгледаме стойностите от extra полето. А те са доста тревожни в случая:
Using temporary това значи че MySQL ще трябва да направи допълнителна временна таблица в която да запише резултата на твърдия диск, което по дефиниция отнема време.
Using filesort означава че MySQL ще трябва да направи допълнително сортиране като мине отново през всички записи - в случая има малко записи, но в таблица с хиляди записи това е ще отнеме доста време.
Using where е точно това, което гласи и името му - в заявката се използва WHERE клауза. Кофтито тука е когато join_type-а е ALL и няма индекс, който да се ползва - пак ще се сканира цялата таблица.
Using join buffer (flat, BNL join) гледам че е алгоритъм на MariaDB, в MySQL най-вероятно ще има друга стойност (нямам в момента друга база да тествам). Но накратко изглежда в този случаи се използват редове записани в буфера при предишен join.
Накратко е това, надявам се да съм събудил интерес поне у някои от вас. Поиграите си с таблиците, слагайте индекси и вижде как се променя изхода от EXPLAIN командата, ако има желаещи може да продължим темата.