Mysql join with group by query optimization
I am using the following query to get the latest articles (article title + author name + total comments) but it takes long time to run:
SELECT article.id, title, username, count( comment.id ) AS total_comments
FROM article
LEFT JOIN COMMENT ON comment.article_id = article.id
LEFT JOIN user ON article.user_id = user.id
WHERE STATUS = "open"
AND section = "mobiles"
GROUP BY article.id
ORDER BY article.id DESC
LIMIT 0 , 30
The output of explain is:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE article ALL status NULL NULL NULL 77 Using where; Using temporary; Using filesort
1 SIMPLE comment ref article_id article_id 5 test.article.id 2
1 SIMPLE user eq_ref PRIMARY PRIMARY 4 test.article.user_id 1
how to re-write the query to avoid creating temporary table?
Storage engine is MyISAM. Here is tables details wit开发者_运维技巧h indexes:
article
id, title, body, user_id, status, section
primary key: id
indexes: (user_i),(status,section,id)
comment
id, article_id, user_id, body
primary key: id
index:(article_id)
user
id, username
primary key: id
Would using a sub query instead of the grouped join speed up the process.
SELECT article.id, title, username,
(
select count(*) from COMMENT
where comment.article_id = article.id
) AS total_comments
FROM article
LEFT JOIN user ON article.user_id = user.id
WHERE STATUS = "open"
AND section = "mobiles"
ORDER BY article.id DESC
LIMIT 0 , 30
as per a previous question How to make a nested query?
I hope this helps.
This execution plan is pretty good. You really can't avoid creating and sorting the temp table: your query calls for a grouped and sorted summary, which is, ummm, a temporary table. If you give your mySQL server process more RAM you may be able to get it to use an in-memory table rather than an on-disk table.
精彩评论