This query is a bit slow, and I’d like to optimize it, any ideas?
SELECT DISTINCT a.id
FROM article a
LEFT JOIN article_comment ac
ON a.id = ac.article_id
LEFT JOIN comment c
ON ac.id = c.id
WHERE a.id IN (SELECT a2.id
FROM article_user_read aur
LEFT JOIN article a2
ON aur.article_id = a2.id
WHERE c.published_date > aur.read_date
AND aur.user_id = 36748
AND aur.followed = 1)
ORDER BY c.published_date DESC
here is the article_user_read table :
CREATE TABLE `article_user_read` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`article_id` int(11) DEFAULT NULL,
`user_id` int(11) DEFAULT NULL,
`read_date` datetime NOT NULL,
`followed` tinyint(1) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `UNIQ_BBE52A0262922701A76ED395` (`article_id`,`user_id`),
KEY `IDX_BBE52A0262922701` (`article_id`),
KEY `IDX_BBE52A02A76ED395` (`user_id`),
CONSTRAINT `article_user_read_ibfk_3` FOREIGN KEY (`article_id`) REFERENCES `article` (`id`),
CONSTRAINT `article_user_read_ibfk_4` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=20193 DEFAULT CHARSET=latin1;
The other are just simple article & user table.
It doesn’t make sense to
LEFT JOINarticle_user_readwitharticle, because you’re interested in articles, so you don’t care if there are articles without a article_user_read relation — that can be optimized to aJOIN.You also only want articles which have a comment after the user reads the article, so the relation between
article,article_commentandcommentmust exist — that can be optimized toJOINs.The main change however, is that you don’t need a correlated sub-query (referencing comment
cin the sub-query), so theJOINbetweenarticle_user_readandarticlecan be pushed to the main query.