2010-10-21 8 views
3

Je cherche un moyen d'optimiser une requête SQL que j'ai. J'essaie d'obtenir combien de poèmes avec un certain genre.La requête SQL imbriquée prend trop de temps

la requête ressemble à ceci:

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

Il prend trop de temps (environ 6-10 secondes), car il ne peut pas utiliser les index (à cause de IN() je pense?). Existe-t-il un moyen de réécrire cette requête de manière différente pour obtenir le même résultat plus rapidement?

Répondre

11

MySQL has a problem avec in où il réévalue à plusieurs reprises des sous-requêtes non corrélées comme si elles étaient corrélées. Est-ce que la réécriture en tant que jointure améliore les choses?

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

Si non, alors d'après this article (voir la section « Comment forcer la requête interne à exécuter en premier ») enveloppant dans une table dérivée pourrait aider.

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

Merci, beaucoup de nouvelles informations pour moi :) –

+0

Réécrire la requête en utilisant JOIN réduit les lignes examinées par une requête de 4266806 à 1644. Fonctionne comme un éclair :) –

1

Vous pouvez également utiliser une clause EXISTS et sur les id en corrélation et les champs 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'; 

différence entre ceci et IN est il va essayer d'utiliser des index qui font la place analyse complète de la table.

Questions connexes