嵌套SQL查询需要太长时间

时间:2010-10-21 13:21:36

标签: sql mysql query-optimization

我正在寻找一种优化我所拥有的SQL查询的方法。我正在努力获得一定数量的诗歌。

查询如下所示:

SELECT
    COUNT(*)  
FROM
    `poems`
WHERE `id` IN (    
                  SELECT `poem_id`
                  FROM `poems_genres`  
                  WHERE `genre_title` = 'derision'
              )
       AND `status` = 'finished';

它需要太长时间(大约6-10秒),因为它不能使用索引(因为我认为IN()?)。有没有办法以不同的方式重写此查询以更快地获得相同的结果?

2 个答案:

答案 0 :(得分:11)

带有in的MySQL has a problem,它反复重新评估不相关的子查询,就好像它们是相关的一样。重写作为联接会改进吗?

SELECT
    COUNT(distinct p.`id`)  
FROM `poems` p
JOIN `poems_genres` pg
ON  p.`id` = pg.`poem_id`  
WHERE pg.`genre_title` = 'derision' AND p.`status` = 'finished';

如果没有,那么根据this article(参见“如何强制内部查询首先执行”部分)将其包装在派生表中可能会有所帮助。

SELECT
    COUNT(*)  
FROM
    `poems`
WHERE `id` IN
(
 select  `poem_id` from ( SELECT `poem_id`
                  FROM `poems_genres`  
                  WHERE `genre_title` = 'derision') x

) AND `status` = 'finished';

答案 1 :(得分:1)

您还可以使用EXISTS子句并关联id和poem_id字段

SELECT
    COUNT(*)  
FROM
    `poems` p1
WHERE EXISTS
(
 SELECT `poem_id`
                  FROM `poems_genres`  pg
                  WHERE `genre_title` = 'derision'  and p1.id = pg.poem_id

) AND `status` = 'finished';

这与IN的区别在于它会尝试使用索引来代替进行全表扫描。