2010-07-28 5 views
2

Récemment j'ai eu ce question, et tout a fonctionné correctement jusqu'à ce que je l'ai envoyé à mon serveur chez DreamHost.Comment puis-je améliorer les performances de cette requête?

La requête ci-dessous semble prendre trop de temps à s'exécuter et je n'arrive pas à comprendre pourquoi tant de lignes sont traitées en même temps. Dans mon serveur local, la même requête a été exécutée en 0,3 seconde.

SELECT feed_entries . * 
FROM feed_entries 
WHERE 
id 
IN (

SELECT e.id 
FROM feed_entries AS e 
INNER JOIN feeds AS f ON e.feed_id = f.id 
INNER JOIN entries_categorias AS ec ON ec.entry_id = e.id 
INNER JOIN categorias AS c ON ec.categoria_id = c.id 
WHERE 
e.deleted =0 
AND 
c.slug 
IN ('entenda', 'google') 
GROUP BY e.id 
HAVING COUNT(DISTINCT ec.id) =2 

) 
ORDER BY date DESC 
LIMIT 1 

C'est le message que je l'ai reçu de l'équipe de soutien:

Eh bien, il ressemble à ce que la requête est verrouillé en raison de ces requêtes comme celui-ci, le traitement 6.5 millions dossiers, pendant 11 secondes.

# Query_time: 11.639269 Lock_time: 0.000192 Rows_sent: 2 Rows_examined: 
6509098 
use desenvolvimentistas; 
SET timestamp=1280325753; 
SELECT `e`.*, `f`.`titulo` AS `feedTitulo`, `f`.`url` AS `feedUrl` FROM 
`feed_entries` AS `e` 
INNER JOIN `feeds` AS `f` ON e.feed_id =f.id WHERE (e.id IN (SELECT 
`e`.`id` FROM `feed_entries` AS `e` 
INNER JOIN `feeds` AS `f` ON e.feed_id =f.id 
INNER JOIN `entries_categorias` AS `ec` ON ec.entry_id =e.id 
INNER JOIN `categorias` AS `c` ON ec.categoria_id =c.id WHERE (e.deleted 
=0) AND (e.id NOT IN ('', '', '842', '853', '774', '878')) AND 
(e.imagem145x145 =1) AND (c.slug IN('destaque-2')) GROUP BY `e`.`id` 
HAVING (COUNT(DISTINCT ec.id) =1))) ORDER BY `e`.`date` DESC LIMIT 4; 

probablement la requête prend .3 secondes pour exécuter sur votre machine locale qui est ralenti, mais il est lent sur nos serveurs car il est en cours d'exécution de la requête 150 à un temps, et chacun traite 15,3 millions d'enregistrements.

moi avions mysql admin a pris un coup d'œil à et il a dit qu'il était tout à fait inefficace et a été surpris de constater que la base de données était même accessible parce que les requêtes avaient tellement enfermés. Il a déclaré que la base de données sera désactivée si continue ainsi et cause problèmes de serveur. Il a dit que vous devriez réparer les lignes examinées ou obtenir un MySQL PS, bien qu'un mysql ps ne le corrigera pas , mais empêchera plutôt la base de données d'être désactivée.

Voici la requête:

# Query_time: 25.944779 Lock_time: 0.000176 Rows_sent: 0 Rows_examined: 
15378209 
use desenvolvimentistas; 
SELECT `feed_entries`.* FROM `feed_entries` WHERE (id IN (SELECT `e`.`id` 
FROM `feed_entries` AS `e` INNER JOIN `feeds` AS `f` ON e.feed_id =f.id 
INNER JOIN `entries_categorias` AS `ec` ON ec.entry_id =e.id INNER JOIN 
`categorias` AS `c` ON ec.categoria_id =c.id WHERE (e.deleted =0) AND 
(c.slug IN('entenda','google')) GROUP BY `e`.`id` HAVING (COUNT(DISTINCT 
ec.id) =2))) ORDER BY `date` DESC LIMIT 1; 

Voici une autre qui doit être fixé:

# Query_time: 27.010857 Lock_time: 0.000165 Rows_sent: 0 Rows_examined: 
15382750 
use desenvolvimentistas; 
SET timestamp=1280325706; 
SELECT `e`.*, `f`.`titulo` AS `feedTitulo`, `f`.`url` AS `feedUrl` FROM 
`feed_entries` AS `e` 
INNER JOIN `feeds` AS `f` ON e.feed_id =f.id WHERE (e.id IN (SELECT 
`e`.`id` FROM `feed_entries` AS `e` 
INNER JOIN `feeds` AS `f` ON e.feed_id =f.id 
INNER JOIN `entries_categorias` AS `ec` ON ec.entry_id =e.id 
INNER JOIN `categorias` AS `c` ON ec.categoria_id =c.id WHERE (e.deleted 
=0) AND (c.slug IN('manchete', 'google')) GROUP BY `e`.`id` HAVING 
(COUNT(DISTINCT ec.id) =2))) ORDER BY `e`.`date` DESC LIMIT 4;7:18 

Répondre

1

Idéalement, une question par question s'il vous plaît - il n'y a pas de limite au nombre de questions que vous pouvez poser, et il minimise les bavardages associés à chaque requête individuelle.

Je re-écrit votre première requête comme:

SELECT t.* 
    FROM feed_entries t 
    WHERE EXISTS(SELECT NULL 
        FROM feed_entries AS e 
        JOIN feeds AS f ON e.feed_id = f.id 
        JOIN entries_categorias AS ec ON ec.entry_id = e.id 
        JOIN categorias AS c ON ec.categoria_id = c.id 
       WHERE e.deleted = 0 
        AND c.slug IN ('entenda', 'google') 
        AND e.id = t.id 
       GROUP BY e.id 
       HAVING COUNT(DISTINCT ec.id) = 2) 
ORDER BY date DESC 
    LIMIT 1 

Index des colonnes utilisées dans les critères de jointure au minimum, sinon déjà.

J'ai vu un commentaire à propos d'une requête en cours d'exécution 150 fois - pourriez-vous élaborer?

+0

Serait-ce une bonne suggestion d'avoir un index sur 'date' aussi, étant donné qu'il passe commande mais ne prend que le meilleur résultat? –

+0

@Neil Trodden: Oui, mais [MySQL a une limite d'espace pour l'allocation d'index (1 000 pour MyISAM, 767 pour InnoDB)] (http://dev.mysql.com/doc/refman/5.0/fr/create-index .html) donc les critères JOIN sont ma première priorité, puis voir ce que je peux faire avec la couverture des index. –

+0

Merci, j'ai réduit le nombre de 150 requêtes et défini les index. Ont également découvert d'autres erreurs. Maintenant c'est bon. –

1

Eh bien la première chose que je voudrais vérifier est que vous avez la corriger les index sur le serveur hébergé. Parfois, les gens oublient de les déplacer lors de la migration des bases de données.

1

vous pouvez toujours mettre en cache ;-)

+0

J'ai déjà le cache. Mais cette erreur doit être corrigée, ma table n'a pas plus de mille lignes. Il a dit que 15 millions ont été traités dans une requête. –

0

Je vais essayer de créer une seule requête de l'intérieure. Puis ajoutez manuellement les identifiants qui en résultent dans l'on externe (où id dans (1,2,3,4,5)). Bien que cela n'améliore pas automatiquement les performances, vous savez au moins ce qui se passe.

La façon dont ils décrivent le problème, il pourrait même être la boucle interne est testée pour chaque enregistrement unique vérifié à partir de la boucle externe, qui serait fixé par cette approche. Bien que je suppose que MySQL serait assez intelligent ne pas gérer cela par lui-même.

Questions connexes