web-dev-qa-db-fra.com

MySql - phase d'envoi lent des données

Une de mes requêtes sur MySQL 5.0.45 est lente dans la phase "envoi de données". La requête est une sélection simple, renvoie environ 300 champs d'ID entier sous forme de jeu de résultats.

 mysql> SELECT source_id Depuis les directions WHERE (id_destination = 10); 
 + ----------- + 
 |. ID_source | 
 + ----------- + 
 | 2 | 
 | 8 | 
...
 | 2563 | 
 + ----------- + 
 341 lignes dans l'ensemble (2.13 sec) 

Je suis sûr de comprendre pourquoi la phase "d'envoi de données" est si lente et ce qui peut être fait pour la rendre rapide. Veuillez noter que j'exécute cette requête sur l'invite MySQL sur le serveur lui-même. Par conséquent, je ne m'attends pas vraiment à ce qu'il consacre autant de temps à l'envoi de données. Des indices?

Si cela peut aider, j'ai 3 champs de texte sur cette table, mais comme ils ne sont pas sélectionnés, je m'attends à ce qu'ils ne soient pas la cause de cette lenteur.

Cette requête s'exécute des milliers de fois par jour et ne peut pas vraiment se permettre d'y passer 2 secondes à chaque fois.

Résultat de profilage:

 mysql> affiche le profil de la requête 4; 
 + -------------------------------- + - -------- + 
 | Statut | Durée | 
 + -------------------------------- + ---------- + 
 (initialisation) | 0,000003 | 
 | vérification du cache de requête pour requête | 0,000051 | 
 | vérification des autorisations | 0,000007 | 
 | Tables d'ouverture | 0,000011 | 
 | Verrouillage du système | 0,000005 | 
 | Serrure de table | 0,000023 | 
 | init | 0,00002 | 
 | optimisation | 0,00001 | 
 | statistiques | 0,00006 | 
 | préparer | 0,000014 | 
 | exécution | 0,000005 | 
 | Envoi de données | 2.127019 | 
 | fin | 0,000015 | 
 | fin de la requête | 0,000004 | 
 | stocker le résultat dans le cache de requêtes | 0,000039 | 
 | libérer des objets | 0,000011 | 
 | tables de fermeture | 0,000007 | 
 | enregistrement de la requête lente | 0.000047 | 
 + -------------------------------- + ---------- + 
 18 lignes dans le jeu (0,00 sec) 

UPDATE: Je suis tombé sur l'URL suivante qui dit

 Chaque heure correspond à la durée écoulée entre l’événement précédent et le nouvel événement. Donc, la ligne: 
 | Envoi de données | 0,00016800 | 
 Signifie que 0,00016800 secondes se sont écoulées entre "exécution" et "envoi de données". C'est, il faut 0,00016800 secondes pour exécuter la requête .

http://forums.mysql.com/read.php?24,241461,242012#msg-242012

Quelqu'un peut-il valider?

27
user107068

Un plan d'explication est généralement le meilleur endroit pour commencer chaque fois que vous avez une requête lente. Pour en avoir un, lancez

DESCRIBE SELECT source_id FROM directions WHERE (destination_id = 10);

Cela vous montrera un tableau listant les étapes nécessaires pour exécuter votre requête. Si vous voyez une grande valeur dans la colonne "lignes" et NULL dans la colonne "clé", cela signifie que votre requête doit analyser un grand nombre de lignes pour déterminer celles à renvoyer.

Dans ce cas, l'ajout d'un index sur destination_id devrait accélérer considérablement votre requête, moyennant un coût supplémentaire pour l'insertion et la suppression rapide (car l'index devra également être mis à jour).

19
Brad B

Vous pourriez probablement regarder la partie matérielle du serveur mysql . As Mysql doc dit:

Envoi de données

L'unité d'exécution lit et traite des lignes pour une instruction SELECT et envoie des données au client. Etant donné que les opérations effectuées pendant cet état tendent à effectuer de grandes quantités d'accès au disque (lectures), il s'agit souvent de l'état le plus long sur la durée de vie d'une requête donnée.

Donc, si votre serveur a des E/S de disque lentes en raison d'un fichier table/base de données énorme ou d'un fichier table de travail désactivé, l'option InnoDB/fragmentation/un RAID/disque défaillant configuré est démarré (attendez bientôt la mort du disque)/pour toute autre raison d'E/S de disque lenteur - il pourrait être raison de l'augmentation considérable de l'étape "Envoi de données" car, à ce stade, le serveur collecte toutes les données demandées sur le disque et les envoie au client.

Bien sûr, vous devriez essayer d’optimiser select pour utiliser d’abord les index et assurez-vous que ce n’est pas un problème de programmation, car cela affecte la plupart du temps cette étape.

6
Ivan

J'avais le même problème: Send Data était très lent, mais j'avais les bons index, etc.

Après avoir beaucoup fouillé, j’ai trouvé que ma join comparait deux champs indexés mais de collation différente: l’un était latin1_swedish_ci et l’autre uft8_general_ci.

Une fois que je les ai envoyés à utf8, la requête était considérablement plus rapide (de 2,7 à 0,002 seconde)

3
Peter Duley

Avez-vous des index sur cette table? Vous avez dit qu'il en retournait environ 300. Mais combien faut-il en chercher pour trouver ces 300?

1
itsmatt

J'ai vécu cela après avoir quitté MySQL 5.5.x vers 5.7.x. Ma requête utilisant les jointures était rapide sous MySQL 5.5 et très lente sous MySQL 5.7.

Le problème était que MySQL 5.7 avait choisi un autre ensemble d'index que MySQL 5.5.

L'ajout de USE INDEX a résolu le problème.

0
BQffen