web-dev-qa-db-fra.com

Tester les performances des requêtes dans mysql

J'essaye d'installer un script qui permettrait de tester les performances des requêtes sur un serveur de développement mysql. Voici plus de détails:

  • J'ai un accès root
  • Je suis le seul utilisateur à accéder au serveur
  • Principalement intéressé par la performance InnoDB
  • Les requêtes que j'optimise sont principalement des requêtes de recherche (SELECT ... LIKE '%xy%')

Ce que je veux faire, c'est créer un environnement de test fiable pour mesurer la vitesse d'une requête unique, sans dépendance à d'autres variables.

Jusqu'à présent, j'utilisais SQL_NO_CACHE , mais parfois, les résultats de ces tests montrent également le comportement de la mise en cache - prenant beaucoup plus de temps à s'exécuter lors de la première exécution et prenant moins de temps lors des exécutions suivantes.

Si quelqu'un peut expliquer ce comportement en détail, je pourrais m'en tenir à l'utilisation de SQL_NO_CACHE; Je pense que cela pourrait être dû au cache du système de fichiers et/ou à la mise en cache des index utilisés pour exécuter la requête, comme l'explique this post. Je ne sais pas quand le pool de tampons et le tampon de clés sont invalidés ni comment ils peuvent interférer avec les tests.

Donc, à moins de redémarrer le serveur mysql, comment recommanderiez-vous de configurer un environnement fiable pour déterminer si une requête donne de meilleurs résultats que l’autre?

23
Unreason

En supposant que vous ne pouvez pas optimiser l'opération LIKE elle-même, vous devez essayer d'optimiser la requête de base sans réduire le nombre de lignes à vérifier.

Quelques choses qui pourraient être utiles pour cela:

rows colonne dans EXPLAIN SELECT ... result. Ensuite, 

mysql> set profiling=1;
mysql> select sql_no_cache * from mytable;
 ...
mysql> show profile;
+--------------------+----------+
| Status             | Duration |
+--------------------+----------+
| starting           | 0.000063 |
| Opening tables     | 0.000009 |
| System lock        | 0.000002 |
| Table lock         | 0.000005 |
| init               | 0.000012 |
| optimizing         | 0.000002 |
| statistics         | 0.000007 |
| preparing          | 0.000005 |
| executing          | 0.000001 |
| Sending data       | 0.001309 |
| end                | 0.000003 |
| query end          | 0.000001 |
| freeing items      | 0.000016 |
| logging slow query | 0.000001 |
| cleaning up        | 0.000001 |
+--------------------+----------+
15 rows in set (0.00 sec)

Ensuite,

mysql> FLUSH STATUS;
mysql> select sql_no_cache * from mytable;
...
mysql> SHOW SESSION STATUS LIKE 'Select%';
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| Select_full_join       | 0     |
| Select_full_range_join | 0     |
| Select_range           | 0     |
| Select_range_check     | 0     |
| Select_scan            | 1     |
+------------------------+-------+
5 rows in set (0.00 sec)

Une autre valeur intéressante est last_query_cost, qui indique le coût coûteux de l'optimisation pour estimer la requête (la valeur correspond au nombre de lectures de pages aléatoires):

mysql> SHOW STATUS LIKE 'last_query_cost';
+-----------------+-------------+
| Variable_name   | Value       |
+-----------------+-------------+
| Last_query_cost | 2635.399000 |
+-----------------+-------------+
1 row in set (0.00 sec)

La documentation MySQL est votre amie.

59
newtover

Cité depuis cette page : Les options SQL_NO_CACHE affectent la mise en cache des résultats de la requête dans le cache de la requête . Si votre table est assez petite, il est possible que la table elle-même soit déjà mise en cache. Puisque vous évitez simplement de mettre en cache les résultats et non les tables, vous obtenez parfois le comportement décrit. Ainsi, comme indiqué dans les autres publications, vous devriez vider vos tables entre les requêtes.

2
ablaeul

Comme le suggère l'article lié, utilisez FLUSH TABLES entre les exécutions de test pour réinitialiser autant que possible (notamment le cache de requête).

Vos tests ne doivent-ils pas tenir compte du fait qu'InnooBD aura lui-même différents états au cours des performances réelles, de sorte que vous serez intéressé par les performances globales sur plusieurs tests? Dans quelle mesure vos tests de performance seront-ils "réels" si vous souhaitez réinitialiser InnoDB à chaque essai? La requête que vous refusez parce qu'elle fonctionne mal immédiatement après le redémarrage pourrait être de loin la meilleure requête après qu'InnoDB se soit un peu réchauffé.

Si j'étais vous, je me concentrerais sur ce que l'optimiseur de requêtes fait séparément des performances d'InnoDB. Il y a beaucoup d'écrits sur la façon de régler InnoDB, mais il est utile d'avoir de bonnes requêtes pour commencer.

Vous pouvez également essayer de mesurer les performances avec des tables MyISAM équivalentes, où FLUSH TABLES vous remettra à un point de départ pratiquement identique.

Avez-vous essayé de désactiver complètement la mise en cache des requêtes? Même avec SQL_NO_CACHE, il y a environ 3% de pénalité pour le cache de requête.

1
David M

Avez-vous envisagé d'utiliser Maatkit ? Une de ses fonctionnalités avec lesquelles je suis un peu familier consiste à capturer des données réseau MySQL avec tcpdump et à traiter le vidage avec mk-query-digest. Cet outil vous permet d’afficher des informations détaillées sur chaque requête. Mais il existe toute une panoplie d’autres outils qui devraient faciliter l’analyse des requêtes.

1

Les requêtes en texte intégral sur InnoDB sont lentes (instructions LIKE "% query%"), vous ne pouvez rien faire pour les optimiser. Les solutions varient en passant de la table que vous interrogez à MyISAM afin que vous puissiez créer des index en texte intégral (que innoDB ne prend pas en charge), en passant par la dénormalisation de la ligne dans des index interrogeables (non recommandé), Doctrine ORM fournit un exemple simple pour savoir comment l'archiver: http://www.doctrine-project.org/documentation/manual/1_1/nl/behaviors:core-behaviors:searchable La solution "appropriée" à votre problème serait d'indexer les informations. vous utilisez des recherches en texte intégral sur, avec une solution comme Sphinx Search ou Apache Solr.

Comme indiqué précédemment, vous devez tenir compte de l'état du cache lors de la comparaison des résultats. Un cache apprêté fournit des requêtes extrêmement performantes. Vous devez tenir compte du pourcentage d'accès au cache d'une requête particulière. Même si la requête est coûteuse, si le taux d'accès au cache est de 99%, les performances moyennes seront très élevées.

Le réglage fin des requêtes n’est pas une solution miracle, vous pourriez peut-être ajouter de la complexité à votre application pour des optimisations qui, dans l’ensemble, sont négligeables dans un environnement de production.

Considérez votre charge de travail, résolvez les requêtes fréquentes et peu performantes (utilisez le slow_query_log dans mysql, ne commencez pas à aveugler l'optimisation des requêtes).

0
mhughes

Vous pouvez essayer le workbench mysql, je pensais qu'il avait un moniteur d'instructions SQL afin que vous puissiez voir à quelle vitesse il est et pourquoi il est rapide 

0
Spidfire