2010-10-29 3 views
2

J'ai une table avec plus de 1 million d'entrées.La requête SELECT est lente (aucun index nécessaire), pourquoi est-elle si lente?

Le problème est lié à la vitesse des requêtes SELECT. Celui-ci est très rapide:

SELECT * 
    FROM tmp_pages_data 
WHERE site_id = 14294 

Showing rows 0 - 29 (1,273,042 total, Query took 0.0009 sec) 

Et celui-ci est très lent:

SELECT * 
    FROM tmp_pages_data 
WHERE page_status = 0 

Showing rows 0 - 29 (15,394 total, Query took 0.3018 sec) 

Il y a un index sur la colonne id, et non nécessaire dans l'une des sélections. Donc il n'y a pas d'index sur le site_id ou l'état de la page.

La requête de 0,30 seconde est très dérangeante, surtout lorsqu'il y a des milliers de requêtes.

Alors, comment cela peut-il être possible? Que puis-je faire pour voir ce qui le ralentit?

+2

Combien de valeurs différentes de 'page_status' avez-vous:' SELECT DISTINCT page_status FROM tmp_pages_data' Parce qu'un index sur la colonne n'aiderait pas s'il n'y a que deux valeurs possibles. –

+1

Quel est le schéma? La première requête peut-elle renvoyer * toutes * les lignes? (1,273,042 ressemble à "plus de 1 million" ...) – Wolfgang

+0

Il y a 5 valeurs pour 'page_status'. @Wolfgang: oui, la première requête renvoie toutes les lignes. Et je ne supprimerai pas la colonne site_id puisque j'en aurai besoin quand la base de données aura plus de 50 millions de lignes – okaybmd

Répondre

4

Que puis-je faire pour voir ce qui le ralentit?

Il est tout à fait évident que ralentit vers le bas - comme vous l'avez signalé vous n'avez pas un index sur la colonne page_status, et vous devriez avoir un. La seule surprise est que votre première requête est si rapide sans l'index. En y regardant de plus près, il semble que quel que soit le client sur lequel vous exécutez ces requêtes, vous ajoutez un LIMIT 30 implicite que vous ne montrez pas dans votre question. Parce qu'il y a tellement de lignes qui correspondent, il ne faut pas longtemps pour trouver les 30 premières, à quel point il peut arrêter la recherche et retourner le résultat. Cependant, votre deuxième requête renvoie moins de lignes correspondantes, ce qui prend plus de temps pour les trouver. Ajouter l'index résoudrait ce problème et rendrait votre requête presque instantanée. Réponse courte: ajoutez un index sur la colonne page_status.

+0

Non, en fait je ne peux pas ajouter d'index, puisque j'utilise beaucoup de MISES A JOUR (plus de 100 par deuxième), et cela ne ferait que ralentir l'ensemble du script. – okaybmd

+0

Et j'ai essayé d'autres requêtes et elles sont rapides aussi (par ex.SELECT * FROM tmp_pages_data WHERE page_type = 'subcat_list_level_1' - Affichage des lignes 0 - 29 (565 au total, requête a pris 0.0009 sec) - encore une fois, il n'y a pas d'index sur page_type – okaybmd

+0

@okaybmd: Alors vous pourriez envisager d'avoir un système hors ligne pour interroger que vous synchronisez une fois par jour afin de ne pas charger votre système principal. Soit cela, ou vivre avec les temps de requête lente. –

2

Ok, à partir de notre discussion dans les commentaires, nous savons maintenant que la base de données sait en quelque sorte que la première requête renverra toutes les lignes. C'est pourquoi c'est si rapide.

La deuxième requête est lente car elle n'a pas d'index. OMG Ponies a déjà indiqué qu'un index normal ne fonctionnera pas parce que la valeur définie est trop petite. Je voudrais juste vous diriger vers 'index bitmap'. Je ne les ai pas encore utilisés mais ils sont connus pour être exactement conçus pour ce cas.

+0

Ok, merci beaucoup. J'ai regardé un peu dans ceci et cela ressemble à une bonne idée. Cependant, MySQL ne supporte pas les index bitmap. Alors maintenant je dois envisager de passer à PostgreSQL ... – okaybmd

+0

Après plus de recherches, PostgreSQL est en fait plus lent que MySQL, donc je ne pense pas que ce soit une option non plus – okaybmd

Questions connexes