2010-10-21 64 views
3

我正在寻找一种方法来优化我有的一个SQL查询。我试图弄清楚某种流派有多少诗。嵌套SQL查询需要太长时间

查询看起来是这样的:

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

花了很长(约6-10秒),因为它不能使用索引(因为在()我觉得呢?)。有没有办法以不同的方式重写此查询以更快地获得相同的结果?

回答

11

MySQL has a problemin它反复重新评估不相关的子查询,就好像它们是相关的。重写为连接是否会改善事物?

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'; 
+0

谢谢,对我有很多新的信息:) – 2010-10-21 14:06:38

+0

使用JOIN重写查询减少了由查询从4266806到1644查询的行。作为闪电工作:) – 2010-10-22 10:17:21

1

您还可以使用EXISTS子句,这之间

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'; 

差异上的ID和poem_id领域的关联和IN是它会尝试使用索引而不是做全表扫描。