2011-05-13 5 views
7

J'ai exécuté la requête suivante à la fois dans phpMyAdmin & MySQLdb (python).MySQLdb est extrêmement lent avec de grands ensembles de résultats

SELECT *, (SELECT CONCAT(`id`, '|', `name`, '|', `image_code`) 
FROM `model_artist` WHERE `id` = `artist_id`) as artist_data, 
FIND_IN_SET("metallica", `searchable_words`) as find_0 
FROM `model_song` HAVING find_0 

phpMyAdmin dit que la requête a 2ms. Mon code python disait qu'en utilisant MySQLdb la requête prenait 848ms (sans même aller chercher les résultats).

Le code python:

self.db = MySQLdb.connect(host="localhost", user="root", passwd="", db="ibeat") 
self.cur = self.db.cursor() 

millis = lambda: time.time() * 1000 

start_time = millis() 
self.cur.execute_cmd("""SELECT *, (SELECT CONCAT(`id`, '|', `name`, '|', `image_code`) 
FROM `model_artist` WHERE `id` = `artist_id`) as artist_data, 
FIND_IN_SET("metallica", `searchable_words`) as find_0 
FROM `model_song` HAVING find_0""") 
print millis() - start_time 
+0

Si vous exécutez cette requête sur la ligne de commande MySQL, quelle heure vous obtenez? – dusan

+0

Combien d'enregistrements sont renvoyés? Êtes-vous _sure_ phpMyAdmin a effectué la requête? –

Répondre

4

PHPMyAdmin place une limite sur toutes les requêtes afin que vous ne retournez pas de grands résultats dans l'interface. Ainsi, si votre requête renvoie normalement 1 000 000 lignes et que PHPMyAdmin réduit ce nombre à 1 000 (ou par défaut), vous devrez attendre un temps de traitement plus long lorsque Python récupère ou même interroge l'ensemble des résultats. Essayez de placer une limite en Python qui correspond à la limite de PHPMyAdmin pour comparer les heures.

+0

Je l'ai compris, mais je n'ai pas vu votre réponse ... Cependant, je vais accepter le vôtre: P –

13

Si vous vous attendez à ce qu'une requête SQL ait un jeu de résultats volumineux que vous prévoyez d'itérer sur enregistrement par enregistrement, vous pouvez envisager d'utiliser le MySQLdb SSCursor au lieu du curseur par défaut. Le curseur par défaut stocke le jeu de résultats dans le client, tandis que le SSCursor stocke le jeu de résultats dans le serveur. Contrairement au curseur par défaut, le SSCursor ne subira pas un délai initial important si tout ce que vous avez à faire est de parcourir les enregistrements un par un.

Vous pouvez trouver un exemple de code sur how to use the SSCursor here.

Par exemple, essayez:

import MySQLdb.cursors 

self.db = MySQLdb.connect(host="localhost", user="root", passwd="", db="ibeat", 
          cursorclass = MySQLdb.cursors.SSCursor) 

(. Le reste du code peut rester la même)

+0

Merci pour info :) –

+3

Ou si vous utilisez DictCursor, remplacez-le par SSDictCursor afin que les résultats sont renvoyés comme une liste de dictionnaires. –

Questions connexes