Reputation: 946
Currently I am facing a rather slow query on a website, which also slows down the server on more traffic. How can I rewrite the query or what index can I write to avoid "Using temporary; Using filesort"? Without "order by" everything works fast, but without the wanted result/order.
SELECT cams.name, models.gender, TIMESTAMPDIFF(YEAR, models.birthdate, CURRENT_DATE) AS age, lcs.viewers
FROM cams
LEFT JOIN cam_tags ON cams.id = cam_tags.cam_id
INNER JOIN tags ON cam_tags.tag_id = tags.id
LEFT JOIN model_cams ON cams.id = model_cams.cam_id
LEFT JOIN models ON model_cams.model_id = models.id
LEFT JOIN latest_cam_stats lcs ON cams.id = lcs.cam_id
WHERE tags.name = '?'
ORDER BY lcs.time_stamp_id DESC, lcs.viewers DESC
LIMIT 24 OFFSET 96;
id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | SIMPLE | tags | NULL | const | PRIMARY,tags_name_uindex | tags_name_uindex | 766 | const | 1 | 100 | Using temporary; Using filesort |
1 | SIMPLE | cam_tags | NULL | ref | PRIMARY,cam_tags_cams_id_fk,cam_tags_tags_id_fk | cam_tags_tags_id_fk | 4 | const | 75565047 | 100 | Using where |
1 | SIMPLE | cams | NULL | eq_ref | PRIMARY | PRIMARY | 4 | cam_tags.cam_id | 1 | 100 | NULL |
1 | SIMPLE | model_cams | NULL | eq_ref | model_platforms_platforms_id_fk | model_platforms_platforms_id_fk | 4 | cam_tags.cam_id | 1 | 100 | NULL |
1 | SIMPLE | models | NULL | eq_ref | PRIMARY | PRIMARY | 4 | model_cams.model_id | 1 | 100 | NULL |
1 | SIMPLE | lcs | NULL | eq_ref | PRIMARY,latest_cam_stats_cam_id_time_stamp_id_viewers_index | PRIMARY | 4 | cam_tags.cam_id | 1 | 100 | NULL |
Upvotes: 0
Views: 1916
Reputation: 142198
There are many cases where it is effectively impossible to avoid "using temporary, using filesort".
"Filesort" does not necessarily involve a "file"; it is often done in RAM. Hence performance may not be noticeably hurt.
That said, I will assume your real question is "How can this query be sped up?".
Most of the tables are accessed via PRIMARY
or "eq_ref" -- all good. But the second table involves touching an estimated 75M rows! Often that happens as the first table, not second. Hmmmm.
Sounds like cam_tags
is a many-to-many mapping table? And it does not have any index starting with name
? See this for proper indexes for such a table: http://mysql.rjweb.org/doc.php/index_cookbook_mysql#many_to_many_mapping_table
Since the WHERE
and ORDER BY
reference more than one table, it is essentially impossible to avoid "using temporary, using filesort".
Worse than that, it needs to find all the ones with "name='?'", sort the list, skip 96 rows, and only finally deliver 24.
Upvotes: 0