[英]Any ideas on how could I optimize this query?
这个查询有点慢,我想对其进行优化,有什么想法吗?
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
这是article_user_read表:
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;
其他只是简单的文章和用户表。
SELECT DISTINCT a.id
FROM article AS a
JOIN article_user_read AS aur
ON aur.article_id = a.id
JOIN comment AS c
ON ac.id = c.id
JOIN article_comment AS ac
ON a.id = ac.article_id
WHERE c.published_date > aur.read_date
AND aur.user_id = 36748
AND aur.followed = 1
ORDER BY c.published_date DESC
用article
来将article_user_read
与LEFT JOIN
article_user_read
是没有意义的,因为您对文章感兴趣,因此您不必担心是否存在没有article_user_read关系的文章-可以将其优化为JOIN
。
您还只希望在用户阅读文章后发表评论的文章,因此article
, article_comment
和comment
之间的关系必须存在-可以优化为JOIN
。
但是主要的变化是,您不需要相关的子查询(在子查询中引用注释c
),因此article_user_read
和article
之间的JOIN
可以推送到主查询中。
一个大胆的猜测:用“ WHERE EXISTS”代替“ IN”通常会得到回报:
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 EXISTS (
SELECT *
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
AND a.id = a2.id
)
ORDER BY c.published_date DESC
鉴于您只对此查询中的文章ID感兴趣,因此可以将其显着简化为:
SELECT a.id
FROM article a
WHERE EXISTS
(SELECT NULL
FROM article_comment ac
INNER JOIN comment c ON ac.id = c.id
INNER JOIN article_user_read aur
ON aur.article_id = a.id AND c.published_date > aur.read_date
WHERE a.id = ac.article_id AND
aur.user_id = 36748 AND
aur.followed = 1)
由于您只关心不同的ID,因此我仅从article_user_read表进行预查询,因为这是WHERE EXISTS的全部基础,然后链接到文章并提取您想要的其他任何列...此外,您正在做LEFT联接,但最终需要根据您各自在“ c.published_date”的WHERE子句进行查找,这意味着所有条目都必须一直到注释表。 所以LEFT JOIN不适用...我唯一要做的就是在用户ID和Followed标志上都向article_user_read表添加索引。
SELECT distinct
aur.article_id
from
article_user_read aur
join article a
on aur.article_id = a.id
join article_comment ac
on aur.article_id = ac.article_id
join comment c
on ac.id = c.id
and c.published_date > aur.read_date
where
aur.user_id = 36748
and aur.followed = 1
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.