繁体   English   中英

关于如何优化此查询的任何想法?

[英]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_readLEFT JOIN article_user_read是没有意义的,因为您对文章感兴趣,因此您不必担心是否存在没有article_user_read关系的文章-可以将其优化为JOIN

您还只希望在用户阅读文章后发表评论的文章,​​因此articlearticle_commentcomment之间的关系必须存在-可以优化为JOIN

但是主要的变化是,您不需要相关的子查询(在子查询中引用注释c ),因此article_user_readarticle之间的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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM