MySQL extrêmement lent sur les requêtes SELECT très simples


10

Nous avons une application Web simple fonctionnant sur une machine virtuelle qui enregistre ses données dans une base de données MySQL 5.5 avec le moteur InnoDB. Tout a bien fonctionné pendant environ trois ans, mais soudain, cela est devenu extrêmement lent.

Par exemple, j'ai une table très simple contenant des adresses:

CREATE TABLE `addresses` (
  `address_id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(64) CHARACTER SET latin1 NOT NULL,
  `firstname` varchar(64) CHARACTER SET latin1 NOT NULL,
  `street` varchar(64) CHARACTER SET latin1 NOT NULL,
  `housenumber` varchar(16) CHARACTER SET latin1 NOT NULL,
  `zip` varchar(5) CHARACTER SET latin1 NOT NULL,
  `city` varchar(64) CHARACTER SET latin1 NOT NULL,
  `email` varchar(64) CHARACTER SET latin1 NOT NULL,
  `phone` varchar(16) CHARACTER SET latin1 NOT NULL,
  `birthdate` date NOT NULL,
  PRIMARY KEY (`address_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin

Ce tableau contient environ 800 entrées, ce qui n'est vraiment pas beaucoup. Mais exécuter la requête

SELECT * FROM addresses

à des fins de test, il semble ne jamais finir. J'ai vérifié cela avec la CLI mysql sur le serveur lui-même: il sort quelques lignes de la table puis attend très longtemps jusqu'à ce qu'il sorte les lignes suivantes.

C'est peut-être un problème dans la phase d'envoi de données, mais je ne suis pas sûr.

La machine virtuelle a 2 Go de RAM et seulement 320 Mo sont utilisés. Le CPU fonctionne également à très faible 1 à 2%. mytop n'affiche aucune autre requête bloquant le serveur. L'administrateur informatique a déclaré qu'il n'avait rien changé du côté matériel.

J'ai déjà essayé quelque chose comme redémarrer le serveur de base de données, redémarrer la machine virtuelle. Rien n'a aidé.

Éditer:

EXPLAIN SELECT * FROM addresses

me donne ce résultat:

+----+-------------+-----------+------+---------------+------+---------+------+------+-------+
| id | select_type | table     | type | possible_keys | key  | key_len | ref  | rows | Extra |
+----+-------------+-----------+------+---------------+------+---------+------+------+-------+
|  1 | SIMPLE      | addresses | ALL  | NULL          | NULL | NULL    | NULL |  793 |       |
+----+-------------+-----------+------+---------------+------+---------+------+------+-------+
1 row in set (0.00 sec)

Virtual Box, Xen ou autre chose? Comment le disque hôte est-il configuré? y a-t-il d'autres VM sur la même boîte qui fonctionnent aussi lentement? Répondre à ces questions pourrait révéler la réponse
Matt

Je ne suis pas le propriétaire de l'hyperviseur, je ne peux donc pas vraiment répondre à cette question. J'ai déjà demandé à l'administrateur de l'hyperviseur s'il était au courant de changements récents, mais il a dit non.
tabb

si vous le pouvez, arrêtez mysql et lancez des tests de performances de disque et de mémoire. Ne doit pas être compliqué. L'idée est de simplement isoler s'il s'agit d'un problème avec mysql, peut-être un problème d'index comme indiqué dans la réponse ci-dessous, ou plus répandu.
Matt

Bon point, je l'ai vécu comme n'étant probablement pas un problème mysql. L'exécution mysql -u username -ppassword mydb -e 'SELECT * FROM addressesest lente, mais en ajoutant `> test.txt`, elle s'exécute très rapidement. Maintenant, ce serait probablement une question différente!? Comment pourrais-je enquêter là-dessus?
tabb

Contactez le propriétaire de l'hyperviseur et demandez-lui de vérifier les journaux pour toute erreur. Plus précisément les erreurs de disque. Dites-lui vos symptômes. Sauvegarder maintenant.
Matt

Réponses:


13

Si la charge du processeur est faible, cela indique qu'il n'y a pas de problème avec les index manquants, si c'était le cas, la requête aurait juste besoin de prendre plus de CPU et d'accès au disque. Vous avez également dit que cela fonctionnait bien pendant 3 ans.

Avez-vous vérifié la vitesse générale d'accès au disque (en particulier sur la partition où se trouve la base de données)? Par exemple en utilisant dd comme ici . Ce que vous décrivez ressemble à un disque mort ou à un raid à moitié mort. Vous avez des sauvegardes j'espère?


C'est un bon point. Cela peut être quelque chose d'aussi simple qu'une erreur de disque sur l'hôte.
Matt

9

Vous pouvez essayer quelques trucs,

  1. Avez-vous configuré des index?

L'indexation permet de trouver rapidement des enregistrements sans effectuer d'abord une analyse complète de la table, ce qui réduit considérablement les temps d'exécution.

CREATE INDEX idx_name ON addresses(name);
  1. Avant d'exécuter la requête, utilisez d'abord le mot clé EXPLAIN,

Lorsqu'il est utilisé devant une requête SELECT, il décrira comment MySQL a l'intention d'exécuter la requête et le nombre de lignes qu'il devra traiter avant de terminer.

  1. Apportez quelques modifications à votre mysql.ini, si c'est une VM, augmentez la RAM et configurez votre mysql.ini pour voir si les performances augmentent.

Il existe de nombreux optimiseurs MySQL qui peuvent vous guider.

Aide cela aide


D'accord, mais la création d'un index sur une table assez petite (<800 lignes) ne semble pas être aussi utile que j'en aurais besoin. Il faut plus d'une minute pour terminer la requête citée ci-dessus. Une analyse complète d'une table aussi petite ne devrait pas prendre si longtemps.
tabb

Alors ... avez-vous ajouté les index? Si vous n'êtes pas sûr du problème, je commencerais par la base et continuerais mon chemin. L'ajout d'index n'augmentera les performances que s'il est effectué correctement.
Anthony Fornito

Oui, j'ai ajouté un index sur la colonne nom. Mais ma requête ci-dessus n'a même pas de clause WHERE restrictive, elle devra donc lire la table entière et l'imprimer. Ajout de l'index n'a pas aidé.
tabb

J'ai ajouté le résultat de la requête EXPLAIN ci-dessus. Cela me semble bien, mais les performances sont toujours très faibles. Je ne peux pas augmenter la RAM car je ne suis pas l'administrateur du gestionnaire de virtualisation. Mais htopmontre que seulement 307 Mo sur 2050 Mo de RAM sont utilisés.
tabb

À propos des index, vous devez vraiment penser aux colonnes à indexer, vous ne voulez pas simplement tout indexer, indexer celles qui ont le plus grand nombre, je fais quelques hypothèses folles à ce sujet mais je commencerais par nameet `` prénom ''. Deuxièmement, êtes-vous sûr d'avoir correctement indexé? possible_keys: NULL si la colonne est NULL, cela indique qu'aucun index pertinent n'a pu être trouvé.
Anthony Fornito
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.