Oto mój przykład zapytania:
SELECT
nickname,
CASE class_id
WHEN 1 THEN 'Druid'
WHEN 2 THEN 'Necromancer'
WHEN 3 THEN 'Mage'
WHEN 4 THEN 'Priest'
WHEN 5 THEN 'Warrior'
WHEN 6 THEN 'Stalker'
WHEN 7 THEN 'Paladin'
WHEN 8 THEN 'Psionic'
END class_name,
ROUND(AVG(level),2) level,
ROUND(AVG(tabard_id),2) tabard,
CASE rank_id
WHEN 1 THEN 'Leader'
WHEN 2 THEN 'Officer'
WHEN 3 THEN 'Veteran'
WHEN 4 THEN 'HonoryMember'
WHEN 5 THEN 'OrdinaryMember'
WHEN 6 THEN 'Alt'
WHEN 7 THEN 'Apprentice'
WHEN 8 THEN 'Penalty'
END rank_name,
ROUND(AVG(loyality),2) loyality,
ROUND((MAX(authority)-MIN(authority))/AVG(tabard_id)) authority_effective,
MAX(authority)-MIN(authority) authority_delta,
MIN(authority) authority_begin,
MAX(authority) authority_end
FROM users
LEFT JOIN level_history ON level_history.users_id = users.id
LEFT JOIN tabard_history ON tabard_history.users_id = users.id
LEFT JOIN rank_history ON rank_history.users_id = users.id
LEFT JOIN loyality_history ON loyality_history.users_id = users.id
LEFT JOIN authority_history ON authority_history.users_id = users.id
LEFT JOIN guilds_has_users ON guilds_has_users.users_id = users.id
LEFT JOIN report ON report.id = authority_history.report_id
AND report.id = level_history.report_id
AND report.id = loyality_history.report_id
AND report.id = rank_history.report_id
AND report.id = tabard_history.report_id
WHERE report.date BETWEEN '2011-10-24 00:00:00' AND '2011-10-30 23:59:59'
AND guilds_has_users.active = 1
GROUP BY users.id;
Wyjaśnij to wybierz:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE guilds_has_users ref fk_guilds_has_users_users1,active_IDX active_IDX 1 const 139 Using where; Using temporary; Using filesort
1 SIMPLE users eq_ref PRIMARY PRIMARY 4 z92985_orlandino.guilds_has_users.users_id 1
1 SIMPLE level_history ref fk_level_history_users1,fk_level_history_report1,u... fk_level_history_users1 4 z92985_orlandino.guilds_has_users.users_id 1 Using where
1 SIMPLE report eq_ref PRIMARY,date_IDX,id_date_IDX PRIMARY 4 z92985_orlandino.level_history.report_id 1 Using where
1 SIMPLE tabard_history ref fk_tabard_history_users1,fk_tabard_history_report1... fk_tabard_history_users1 4 z92985_orlandino.level_history.users_id 1 Using where
1 SIMPLE rank_history ref fk_rank_history_users1,fk_rank_history_report1,use... fk_rank_history_users1 4 z92985_orlandino.users.id 1 Using where
1 SIMPLE loyality_history ref fk_loyality_history_users1,fk_loyality_history_rep... fk_loyality_history_users1 4 z92985_orlandino.rank_history.users_id 1 Using where
1 SIMPLE authority_history ref fk_authority_history_users1,fk_authority_history_r... fk_authority_history_users1 4 z92985_orlandino.level_history.users_id 1 Using where
Profilowanie tego wyboru mówi mi:
(139 total, Query took 4.4918 sec)
Copying to tmp table 4.488318
I kilka informacji o zmiennych MySQL:
SHOW VARIABLES LIKE '%buffer%';
Variable_name Value
bulk_insert_buffer_size 8388608
join_buffer_size 131072
key_buffer_size 12884901888
myisam_sort_buffer_size 8388608
net_buffer_length 16384
preload_buffer_size 32768
read_buffer_size 131072
read_rnd_buffer_size 25165824
sort_buffer_size 2097144
sql_buffer_result OFF
Dlaczego kopiowanie do tabeli tmp jest tak wolne? Jak poprawić szybkość mojego zapytania?
PS: Nie mogę skonfigurować MySQL, ponieważ mój dostawca hostingu nie pozwala na to.
mysql
optimization
Gofrolista
źródło
źródło
Czy można zredukować zapytanie do tylko tych tabel, które są absolutnie niezbędne do wygenerowania danych wyjściowych, lub podzielić zapytanie na wiele oddzielnych zapytań, aby pobrać różne części informacji?
Może się okazać, że uruchomienie trzech osobnych zapytań na danych będzie szybsze niż uruchomienie jednego dużego - szczególnie, gdy baza danych zacznie rosnąć do dziesiątek i setek tysięcy wierszy.
Zauważyłem też z własnej pracy, że
LEFT JOIN
zapytania niekoniecznie są najbardziej wydajne, więc używaj ich tylko wtedy, gdy jest to absolutnie konieczne ...Mam nadzieję, że to pomoże :)
źródło