Comment mesurer les performances d’une requête MySQL avec mysqlslap

introduction

MySQL est fourni avec un petit outil de diagnostic pratique appelé * mysqlslap * qui existe depuis la version 5.1.4. C’est un outil d’analyse comparative qui peut aider les administrateurs de base de données et les développeurs à tester en charge leurs serveurs de base de données.

mysqlslap peut émuler un grand nombre de connexions client frappant le serveur de base de données en même temps. Les paramètres de test de charge sont entièrement configurables et les résultats de différents tests peuvent être utilisés pour affiner la conception de la base de données ou les ressources matérielles.

Dans ce didacticiel, nous allons apprendre à utiliser mysqlslap pour tester en charge une base de données MySQL avec quelques requêtes élémentaires et à voir comment le benchmarking peut nous aider à affiner ces requêtes. Après quelques démonstrations de base, nous allons passer en revue un scénario de test assez réaliste dans lequel nous créons une copie d’une base de données existante pour le test, analysons les requêtes d’un journal et exécutons le test à partir d’un script.

Les commandes, les packages et les fichiers présentés dans ce didacticiel ont été testés sur * CentOS 7 *. Les concepts restent les mêmes pour les autres distributions.

Quelle taille de serveur devrais-je utiliser?

Si vous souhaitez analyser un serveur de base de données spécifique, vous devez effectuer un test sur un serveur présentant les mêmes spécifications et avec une copie exacte de votre base de données installée.

Si vous souhaitez parcourir ce didacticiel à des fins d’apprentissage et exécuter toutes les commandes qu’il contient, nous vous recommandons au moins un * 2 Go * Droplet. Comme les commandes de ce didacticiel sont censées taxer le serveur, vous constaterez peut-être qu’elles expirent sur un serveur plus petit.

L’exemple de sortie de ce tutoriel a été produit de différentes manières pour optimiser les exemples d’enseignement.

Première étape - Installer MySQL Community Server sur un système de test

Nous allons commencer par installer une nouvelle copie de MySQL Community Server sur une base de données de test. * Vous ne devez exécuter aucune commande ou requête de ce didacticiel sur un serveur de base de données de production. *

Ces tests ont pour but de stresser le serveur de test et peuvent provoquer des retards ou des temps d’arrêt sur un serveur de production. Ce tutoriel a été testé avec l’environnement suivant:

Tout d’abord, nous allons créer un répertoire contenant tous les fichiers liés à ce tutoriel. Cela aidera à garder les choses en ordre. Naviguez dans ce répertoire:

sudo mkdir /mysqlslap_tutorial
cd /mysqlslap_tutorial

Ensuite, nous allons télécharger le référentiel yum MySQL Community Release. Le référentiel que nous téléchargeons est destiné à Red Hat Enterprise Linux 7, qui fonctionne pour CentOS 7:

sudo wget http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm

Ensuite, nous pouvons exécuter la commande + rpm -Uvh + pour installer le référentiel:

sudo rpm -Uvh mysql-community-release-el7-5.noarch.rpm

Vérifiez que les référentiels ont été installés en consultant le contenu du dossier + / etc / yum.repos.d +:

sudo ls -l /etc/yum.repos.d

Le résultat devrait ressembler à ceci:

-rw-r--r--. 1 root root 1612 Jul  4 21:00 CentOS-Base.repo
-rw-r--r--. 1 root root  640 Jul  4 21:00 CentOS-Debuginfo.repo
-rw-r--r--. 1 root root 1331 Jul  4 21:00 CentOS-Sources.repo
-rw-r--r--. 1 root root  156 Jul  4 21:00 CentOS-Vault.repo
-rw-r--r--. 1 root root 1209 Jan 29  2014 mysql-community.repo
-rw-r--r--. 1 root root 1060 Jan 29  2014 mysql-community-source.repo

Nous pouvons également vérifier que la version correcte de MySQL est activée pour l’installation:

sudo yum repolist enabled | grep mysql

Dans notre cas, * MySQL 5.6 Community Server * est ce que nous voulions:

mysql-connectors-community/x86_64       MySQL Connectors Community           10
mysql-tools-community/x86_64            MySQL Tools Community                 6
mysql56-community/x86_64                MySQL 5.6 Community Server           64

Installez le serveur MySQL Community:

sudo yum install mysql-community-server

Une fois le processus terminé, vérifions les composants installés:

sudo yum list installed | grep mysql

La liste devrait ressembler à ceci:

mysql-community-client.x86_64      5.6.20-4.el7      @mysql56-community
mysql-community-common.x86_64      5.6.20-4.el7      @mysql56-community
mysql-community-libs.x86_64        5.6.20-4.el7      @mysql56-community
mysql-community-release.noarch     el7-5             installed
mysql-community-server.x86_64      5.6.20-4.el7      @mysql56-community

Ensuite, nous devons nous assurer que le démon MySQL est en cours d’exécution et démarre automatiquement au démarrage du serveur. Vérifiez l’état du démon mysqld.

sudo systemctl status mysqld.service

S’il est arrêté, il affichera cette sortie:

mysqld.service - MySQL Community Server
  Loaded: loaded (/usr/lib/systemd/system/mysqld.service; disabled)
  Active: inactive (dead)

Démarrer le service:

sudo systemctl start mysqld.service

Assurez-vous qu’il est configuré pour démarrer automatiquement au démarrage:

sudo systemctl enable mysqld.service

Enfin, nous devons sécuriser MySQL:

sudo mysql_secure_installation

Cela fera apparaître une série d’invites. Nous allons montrer les invites ci-dessous, avec les réponses que vous devriez entrer. Au début, l’utilisateur root de MySQL n’a pas de mot de passe. Il vous suffit donc d’appuyer sur * Entrée *.

Aux invites, vous devrez fournir un nouveau mot de passe root sécurisé que vous devrez choisir vous-même. Vous devez répondre * y * pour supprimer le compte d’utilisateur de la base de données anonyme, désactiver le nom de connexion root distant, recharger les tables de privilèges, etc.:

...
Enter current password for root (enter for none):
OK, successfully used password, moving on...
...
Set root password? [Y/n]
New password:
Re-enter new password:
Password updated successfully!
Reloading privilege tables..
... Success!
...
Remove anonymous users? [Y/n]
... Success!
...
Disallow root login remotely? [Y/n]
... Success!
Remove test database and access to it? [Y/n]
- Dropping test database...
... Success!
...
Reload privilege tables now? [Y/n]
... Success!
Cleaning up...

Nous pouvons maintenant nous connecter à la base de données et nous assurer que tout fonctionne correctement:

sudo mysql -h localhost -u root -p

Entrez le mot de passe MySQL racine que vous venez de définir à l’invite. Vous devriez voir une sortie comme celle-ci:

Enter password:
Welcome to the MySQL monitor....

mysql>

À l’invite, entrez la commande pour afficher toutes vos bases de données:

show databases;

Vous devriez voir une sortie comme celle-ci:

+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
+--------------------+
3 rows in set (0.00 sec)

Enfin, créons un compte utilisateur appelé. Ce compte sera utilisé pour vous connecter à MySQL au lieu de l’utilisateur root. Assurez-vous de remplacer par votre propre mot de passe pour cet utilisateur. Nous accorderons également tous les privilèges à ce compte. À l’invite de MySQL, entrez les commandes suivantes:

create user sysadmin identified by '';

Sortie:

Query OK, 0 rows affected (0.00 sec)

Accorder les privilèges:

grant all on *.* to sysadmin;

Sortie:

Query OK, 0 rows affected (0.01 sec)

Revenons à l’invite du système d’exploitation pour le moment:

quit;

Sortie:

Bye

Deuxième étape - Installation d’une base de données exemple

Ensuite, nous devons installer un exemple de base de données pour les tests. Cette base de données s’appelle * employés * et est de manière libre depuis le site Web de MySQL. La base de données peut également être téléchargée à partir de Launchpad. La base de données des employés a été développée par Patrick Crews et Giuseppe Maxia. Les données originales ont été créées par Fusheng Wang et Carlo Zaniolo de Siemens Corporate Research.

Nous choisissons la base de données des employés car elle contient un grand ensemble de données. La structure de la base de données est assez simple: elle n’a que six tables; mais les données qu’elle contient contiennent plus de 3 000 000 d’enregistrements d’employés (la table des salaires compte elle-même près de trois millions de lignes). Cela nous aidera à imiter une charge de travail de production plus réaliste.

Premièrement, s’assurons que nous sommes dans le répertoire:

cd /mysqlslap_tutorial

Téléchargez la dernière version de la base de données exemple d’employés:

sudo wget https://launchpad.net/test-db/employees-db-1/1.0.6/+download/employees_db-full-1.0.6.tar.bz2

Installez l’outil bzip2 pour pouvoir décompresser l’archive:

sudo yum install bzip2

Décompressez l’archive de la base de données. Cela va prendre une minute. Nous le faisons en deux étapes ici:

sudo bzip2 -dfv employees_db-full-1.0.6.tar.bz2
sudo tar -xf employees_db-full-1.0.6.tar

Le contenu sera décompressé dans un nouveau répertoire séparé appelé. Nous devons naviguer dans ce répertoire pour exécuter la requête qui installe la base de données. Le contenu comprend un document README, un journal des modifications, des vidages de données et divers fichiers de requête SQL qui créeront les structures de base de données:

cd employees_db
ls -l

Voici ce que vous devriez voir:

-rw-r--r--. 1 501 games       752 Mar 30  2009 Changelog
-rw-r--r--. 1 501 games      6460 Oct  9  2008 employees_partitioned2.sql
-rw-r--r--. 1 501 games      7624 Feb  6  2009 employees_partitioned3.sql
-rw-r--r--. 1 501 games      5660 Feb  6  2009 employees_partitioned.sql
-rw-r--r--. 1 501 games      3861 Nov 28  2008 employees.sql
-rw-r--r--. 1 501 games       241 Jul 30  2008 load_departments.dump
-rw-r--r--. 1 501 games  13828291 Mar 30  2009 load_dept_emp.dump
-rw-r--r--. 1 501 games      1043 Jul 30  2008 load_dept_manager.dump
-rw-r--r--. 1 501 games  17422825 Jul 30  2008 load_employees.dump
-rw-r--r--. 1 501 games 115848997 Jul 30  2008 load_salaries.dump
-rw-r--r--. 1 501 games  21265449 Jul 30  2008 load_titles.dump
-rw-r--r--. 1 501 games      3889 Mar 30  2009 objects.sql
-rw-r--r--. 1 501 games      2211 Jul 30  2008 README
-rw-r--r--. 1 501 games      4455 Mar 30  2009 test_employees_md5.sql
-rw-r--r--. 1 501 games      4450 Mar 30  2009 test_employees_sha.sql

Exécutez cette commande pour vous connecter à MySQL et exécutez le script qui crée la base de données et charge les données:

sudo mysql -h localhost -u sysadmin -p -t < employees.sql

À l’invite, entrez le mot de passe que vous avez créé pour l’utilisateur * sysadmin * MySQL dans la section précédente.

La sortie du processus ressemblera à ceci. Il faudra environ une minute pour exécuter:

+-----------------------------+
| INFO                        |
+-----------------------------+
| CREATING DATABASE STRUCTURE |
+-----------------------------+
+------------------------+
| INFO                   |
+------------------------+
| storage engine: InnoDB |
+------------------------+
+---------------------+
| INFO                |
+---------------------+
| LOADING departments |
+---------------------+
+-------------------+
| INFO              |
+-------------------+
| LOADING employees |
+-------------------+
+------------------+
| INFO             |
+------------------+
| LOADING dept_emp |
+------------------+
+----------------------+
| INFO                 |
+----------------------+
| LOADING dept_manager |
+----------------------+
+----------------+
| INFO           |
+----------------+
| LOADING titles |
+----------------+
+------------------+
| INFO             |
+------------------+
| LOADING salaries |
+------------------+

Maintenant, vous pouvez vous connecter à MySQL et exécuter des requêtes de base pour vérifier que les données ont été importées avec succès.

sudo mysql -h localhost -u sysadmin -p

Entrez le mot de passe de l’utilisateur * sysadmin * MySQL.

Vérifiez la liste des bases de données pour la nouvelle base de données:

show databases;

Sortie:

+--------------------+
| Database           |
+--------------------+
| information_schema |
| employees          |
| mysql              |
| performance_schema |
+--------------------+
4 rows in set (0.01 sec)

Utilisez la base de données des employés:

use employees;

Vérifiez les tableaux qu’il contient:

show tables;

Sortie:

+---------------------+
| Tables_in_employees |
+---------------------+
| departments         |
| dept_emp            |
| dept_manager        |
| employees           |
| salaries            |
| titles              |
+---------------------+
6 rows in set (0.01 sec)

Si vous le souhaitez, vous pouvez vérifier les détails de chacune de ces tables. Nous allons simplement vérifier les informations pour la table:

describe titles;

Sortie:

+-----------+-------------+------+-----+---------+-------+
| Field     | Type        | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| emp_no    | int(11)     | NO   | PRI | NULL    |       |
| title     | varchar(50) | NO   | PRI | NULL    |       |
| from_date | date        | NO   | PRI | NULL    |       |
| to_date   | date        | YES  |     | NULL    |       |
+-----------+-------------+------+-----+---------+-------+
4 rows in set (0.01 sec)

Vérifiez le nombre d’entrées:

mysql> select count(*) from titles;
+----------+
| count(*) |
+----------+
|   443308 |
+----------+
1 row in set (0.14 sec)

Cochez les autres données souhaitées. Nous pouvons maintenant revenir à l’invite de notre système d’exploitation:

quit;

Troisième étape - Utiliser mysqlslap

Nous pouvons maintenant commencer à utiliser mysqlslap. mysqlslap peut être appelé à partir d’une invite de shell classique, il n’est donc pas nécessaire de se connecter explicitement à MySQL. Pour ce tutoriel, cependant, nous allons ouvrir une autre connexion de terminal à notre serveur Linux et démarrer une nouvelle session MySQL à partir de là avec l’utilisateur * sysadmin * que nous avons créé précédemment, afin de pouvoir vérifier et mettre à jour quelques choses dans MySQL plus facilement. Donc, nous aurons une invite ouverte avec notre utilisateur sudo, et une invite connectée à MySQL.

Avant d’entrer dans des commandes spécifiques pour les tests, vous voudrez peut-être jeter un coup d’œil à cette liste des options les plus utiles de mysqlslap. Cela peut vous aider à concevoir vos propres commandes mysqlslap ultérieurement.

Option What it means

–user

MySQL username to connect to the database server

–password

Password for the user account. It’s best to leave it blank in command line

–host

MySQL database server name

–port

Port number for connecting to MySQL if the default is not used

–concurrency

The number of simultaneous client connections mysqlslap will emulate

–iterations

The number of times the test query will be run

–create-schema

The schema in which to run the tests

–query

The query to execute. This can either be a SQL query string or a path to a SQL script file

–create

The query to create a table. Again, this can be a query string or a path to a SQL file

–delimiter

The delimiter used to separate multiple SQL statements

–engine

The MySQL database engine to use (e.g., InnoDB)

–auto-generate-sql

Lets MySQL perform load testing with its own auto-generated SQL command

Cas d’utilisation: analyse comparative avec SQL et données générés automatiquement

Nous allons commencer par utiliser la fonctionnalité auto-generate-sql de mysqlslap. Lorsque nous utilisons du SQL généré automatiquement, mysqlslap crée une base de données temporaire distincte - appelée à juste titre mysqlslap. Cette base de données contiendra une table simple contenant un entier et une colonne de type varchar contenant des exemples de données. Cela peut constituer un moyen simple et rapide de vérifier les performances globales du serveur de base de données.

Nous commençons par tester une seule connexion client en effectuant une itération d’un SQL généré automatiquement:

sudo mysqlslap --user=sysadmin --password --host=localhost  --auto-generate-sql --verbose

Le résultat devrait ressembler à ceci:

Benchmark
       Average number of seconds to run all queries: 0.009 seconds
       Minimum number of seconds to run all queries: 0.009 seconds
       Maximum number of seconds to run all queries: 0.009 seconds
       Number of clients running queries: 1
       Average number of queries per client: 0

mysqlslap rapporte quelques statistiques de benchmarking, comme indiqué dans le résultat. Il indique le nombre moyen, minimum et maximum de secondes nécessaires à l’exécution de la requête. Nous pouvons également constater que le nombre de connexions client utilisées pour ce test de charge était égal à un.

Maintenant, essayez 50 connexions simultanées et faites exécuter la requête générée automatiquement 10 fois:

sudo mysqlslap --user=sysadmin --password --host=localhost  --concurrency=50 --iterations=10 --auto-generate-sql --verbose

Cette commande signifie que cinquante connexions client simulées lancent chacune la même requête de test au même moment et que le test est répété dix fois.

La sortie nous montre une différence marquée avec la charge accrue:

Benchmark
       Average number of seconds to run all queries: 0.197 seconds
       Minimum number of seconds to run all queries: 0.168 seconds
       Maximum number of seconds to run all queries: 0.399 seconds
       Number of clients running queries: 50
       Average number of queries per client: 0

Notez que le champ affiche maintenant une valeur de 50. Le nombre moyen de requêtes par client est égal à zéro.

Le SQL généré automatiquement crée une table simple avec deux champs. Dans la plupart des environnements de production, les structures de table seront beaucoup plus grandes que cela. Mysqlslap peut émuler ceci en ajoutant des champs supplémentaires à la table de test. Pour ce faire, nous pouvons utiliser deux nouveaux paramètres: + - number-char-cols + et + - number-int-cols +. Ces paramètres spécifient le nombre de types varchar et int de colonnes à ajouter à la table de test.

Dans l’exemple suivant, nous testons avec une requête SQL générée automatiquement qui s’exécute sur une table avec 5 colonnes numériques et 20 colonnes de type caractères. Nous simulons également 50 connexions client et nous souhaitons que le test soit répété 100 fois:

sudo mysqlslap --user=sysadmin --password --host=localhost  --concurrency=50 --iterations=100 --number-int-cols=5 --number-char-cols=20 --auto-generate-sql --verbose

Celui-ci devrait prendre un peu plus longtemps. Pendant le test, nous pouvons passer à l’autre fenêtre de terminal où une session MySQL est en cours d’exécution et voir ce qui se passe. Notez que si vous attendez trop longtemps, le test sera terminé et vous ne pourrez pas voir la base de données de tests.

Depuis l’invite MySQL:

show databases;

Notez la base de données:

+--------------------+
| Database           |
+--------------------+
| information_schema |
| employees          |
| mysql              |
| mysqlslap          |
| performance_schema |
+--------------------+
5 rows in set (0.01 sec)

Vous pouvez vérifier la table dans la base de données de test si vous le souhaitez. cela s’appelle * t1 *.

Vérifiez votre autre fenêtre de terminal à nouveau. Une fois le test terminé, vous constaterez que les performances ont encore ralenti avec l’augmentation de la charge:

Benchmark
       Average number of seconds to run all queries: 0.695 seconds
       Minimum number of seconds to run all queries: 0.627 seconds
       Maximum number of seconds to run all queries: 1.442 seconds
       Number of clients running queries: 50
       Average number of queries per client: 0

Retournez à votre session de terminal MySQL. Nous pouvons voir que mysqlslap a abandonné sa base de données jetable. À l’invite de MySQL:

show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| employees          |
| mysql              |
| performance_schema |
+--------------------+
4 rows in set (0.00 sec)

Cas d’utilisation: analyse comparative avec des requêtes personnalisées

Le SQL généré automatiquement est utile si vous évaluez les ressources physiques du serveur. C’est utile lorsque vous voulez trouver le niveau de charge que peut supporter un système donné.

Toutefois, lorsque vous souhaitez résoudre les problèmes de performances pour une application dépendante de la base de données, vous devez tester des requêtes réelles sur des données réelles. Ces requêtes peuvent provenir de votre serveur Web ou d’application.

Pour le moment, nous supposerons que vous connaissez la requête spécifique que vous souhaitez tester. Dans la section suivante, nous allons vous montrer un moyen de rechercher les requêtes en cours d’exécution sur votre serveur.

Nous allons commencer par les requêtes en ligne. Vous pouvez donner une requête en ligne à mysqlslap avec l’option. Les instructions SQL ne peuvent pas comporter de sauts de ligne et doivent être délimitées par des points-virgules (;). Les requêtes doivent également être placées entre guillemets.

Dans l’extrait de code suivant, nous exécutons une requête simple sur la table. La table deptemp a plus de trois cent mille enregistrements. Notez comment nous avons spécifié la base de données avec l’option:

sudo mysqlslap --user=sysadmin --password --host=localhost  --concurrency=50 --iterations=10 --create-schema=employees --query="SELECT * FROM dept_emp;" --verbose

Cela prendra un certain temps à courir. Vous devriez recevoir un repère de performance comme celui-ci après une minute ou deux:

Benchmark
       Average number of seconds to run all queries: 18.486 seconds
       Minimum number of seconds to run all queries: 15.590 seconds
       Maximum number of seconds to run all queries: 28.381 seconds
       Number of clients running queries: 50
       Average number of queries per client: 1

(Remarque: si cette requête s’interrompt pendant plus de dix minutes ou ne produit aucun résultat, vous devez réessayer avec un nombre inférieur pour et / ou, ou essayez-le sur un serveur plus gros.)

Ensuite, nous allons utiliser plusieurs instructions SQL dans le paramètre. Dans l’exemple suivant, nous terminons chaque requête par un point-virgule. mysqlslap sait que nous utilisons un certain nombre de commandes SQL distinctes car nous avons spécifié l’option:

sudo mysqlslap --user=sysadmin --password --host=localhost  --concurrency=20 --iterations=10 --create-schema=employees --query="SELECT * FROM employees;SELECT * FROM titles;SELECT * FROM dept_emp;SELECT * FROM dept_manager;SELECT * FROM departments;" --delimiter=";" --verbose

Ce test utilise le même nombre de connexions et le même nombre d’itérations. Cependant, les performances ont été progressivement plus lentes pour plusieurs instructions SELECT (en moyenne 23,8 secondes par rapport à 18.486 secondes):

Benchmark
       Average number of seconds to run all queries: 23.800 seconds
       Minimum number of seconds to run all queries: 22.751 seconds
       Maximum number of seconds to run all queries: 26.788 seconds
       Number of clients running queries: 20
       Average number of queries per client: 5

Les instructions SQL de production peuvent être compliquées. Il est plus facile d’ajouter une instruction SQL compliquée à un script que de la saisir à des fins de test. Donc, nous pouvons demander à mysqlslap de lire la requête depuis un fichier script.

Pour illustrer cela, créons un fichier de script à partir des commandes SQL. Nous pouvons utiliser l’extrait de code ci-dessous pour créer un tel fichier:

sudo echo "SELECT * FROM employees;SELECT * FROM titles;SELECT * FROM dept_emp;SELECT * FROM dept_manager;SELECT * FROM departments;" > ~/select_query.sql

sudo cp ~/select_query.sql /mysqlslap_tutorial/

Le fichier contient maintenant les cinq instructions SELECT.

Comme ce script contient plusieurs requêtes, nous pouvons introduire un nouveau concept de test. mysqlslap peut paralléliser les requêtes. Nous pouvons le faire en spécifiant le nombre de requêtes que chaque client de test doit exécuter. mysqlslap le fait avec l’option. Ainsi, si nous avons 50 connexions et 1 000 requêtes à exécuter, chaque client exécutera environ 20 requêtes chacune.

Enfin, nous pouvons également utiliser le commutateur, ce qui nous donnera une indication des ressources informatiques utilisées.

Dans l’extrait de code suivant, nous demandons à mysqlslap d’utiliser le fichier de script que nous venons de créer. Nous spécifions également le paramètre. Le processus sera répété deux fois et nous voulons des informations de débogage dans la sortie:

sudo mysqlslap --user=sysadmin --password --host=localhost  --concurrency=20 --number-of-queries=1000 --create-schema=employees --query="/mysqlslap_tutorial/select_query.sql" --delimiter=";" --verbose --iterations=2 --debug-info

Une fois cette commande terminée, nous pouvons voir des résultats intéressants:

Benchmark
       Average number of seconds to run all queries: 217.151 seconds
       Minimum number of seconds to run all queries: 213.368 seconds
       Maximum number of seconds to run all queries: 220.934 seconds
       Number of clients running queries: 20
       Average number of queries per client: 50


User time 58.16, System time 18.31
Maximum resident set size 909008, Integral resident set size 0
Non-physical pagefaults 2353672, Physical pagefaults 0, Swaps 0
Blocks in 0 out 0, Messages in 0 out 0, Signals 0
Voluntary context switches 102785, Involuntary context switches 43

Ici, le nombre moyen de secondes pour exécuter toutes les requêtes dans notre instance MySQL est de 217 secondes, soit presque 4 minutes. Cela a certes été affecté par la quantité de RAM et de CPU disponible sur notre machine virtuelle, mais également par le grand nombre de requêtes d’un nombre modéré de connexions client répétées deux fois.

Nous pouvons voir qu’il y avait un grand nombre de défauts de page non physiques. Les erreurs de page se produisent lorsque des données ne peuvent pas être trouvées dans la mémoire et que le système doit aller les chercher à partir du fichier d’échange sur le disque. La sortie affiche également des informations relatives à la CPU. Dans ce cas, nous voyons un grand nombre de changements de contexte.

Cas d’utilisation: scénario d’analyse comparative pratique et capture de requêtes en direct

Jusqu’à présent, dans nos exemples, nous avons exécuté des requêtes sur la base de données d’employés d’origine. C’est quelque chose que les administrateurs de base de données ne voudraient certainement pas que vous fassiez. Et il y a une bonne raison pour cela. Vous ne voulez pas ajouter de charge à votre base de données de production ni d’exécuter des requêtes de test susceptibles de supprimer, mettre à jour ou insérer des données dans vos tables de production.

Nous allons vous montrer comment faire une sauvegarde d’une base de données de production et la copier dans un environnement de test. Dans cet exemple, il se trouve sur le même serveur, mais vous devriez idéalement le copier sur un serveur distinct doté de la même capacité matérielle.

Plus important encore, nous allons vous montrer comment enregistrer des requêtes en direct à partir de la base de données de production et les ajouter à un script de test. Autrement dit, vous obtiendrez des requêtes de la base de production, mais vous pourrez exécuter des tests sur la base de tests.

Les étapes générales sont les suivantes et vous pouvez les utiliser pour n’importe quel test mysqlslap:

  • 1. * Copiez la base de données de production dans un environnement de test. + 2. Configurez MySQL pour enregistrer et capturer toutes les demandes de connexion et requêtes sur la base de production. + * 3. * Simulez le cas d’utilisation que vous essayez de tester. Par exemple, si vous exécutez un panier, vous devez acheter quelque chose qui déclenchera toutes les requêtes de base de données appropriées à partir de votre application. + * 4. * Désactive l’enregistrement de la requête. + * 5. * Consultez le journal des requêtes et dressez une liste des requêtes que vous souhaitez tester. + * 6. * Créez un fichier de test pour chaque requête à tester. + * 7. * Lancer les tests. + * 8. * Utilisez le résultat pour améliorer les performances de votre base de données.

Commençons par créer une sauvegarde de la base de données des employés. Nous allons créer un répertoire séparé pour sa sauvegarde:

sudo mkdir /mysqlslap_tutorial/mysqlbackup

cd /mysqlslap_tutorial/mysqlbackup

Créez la sauvegarde et déplacez-la dans le nouveau répertoire:

sudo mysqldump --user sysadmin --password --host localhost employees > ~/employees_backup.sql

sudo cp ~/employees_backup.sql /mysqlslap_tutorial/mysqlbackup/

Allez sur votre serveur de test MySQL. Créer la base de données:

CREATE DATABASE employees_backup;

À ce stade, si vous utilisez un serveur séparé pour les tests, vous devez y copier le fichier. À partir de votre session de terminal principale, importez les données de sauvegarde dans la base de données:

sudo mysql -u sysadmin -p employees_backup < /mysqlslap_tutorial/mysqlbackup/employees_backup.sql

Sur votre * serveur de base de données MySQL * de production, activez le journal de requête général MySQL et attribuez-lui un nom de fichier. Le journal de requête général capture les activités de connexion, déconnexion et requête pour une instance de base de données MySQL.

SET GLOBAL general_log=1, general_log_file='capture_queries.log';

Exécutez maintenant les requêtes que vous souhaitez tester sur le serveur de production MySQL. Dans cet exemple, nous allons lancer une requête à partir de la ligne de commande. Toutefois, vous souhaiterez peut-être générer des requêtes à partir de votre application au lieu de les exécuter directement. Si vous souhaitez tester un processus ou une page Web lent, vous devez l’exécuter ou accéder à cette page Web maintenant. Par exemple, si vous exécutez un panier, vous souhaiterez peut-être terminer le processus de paiement maintenant, ce qui déclenchera toutes les requêtes appropriées sur le serveur de base de données.

C’est la requête que nous allons exécuter sur le serveur de production MySQL. Commencez par utiliser la bonne base de données:

USE employees;

Maintenant, lancez la requête:

SELECT e.first_name, e.last_name, d.dept_name, t.title, t.from_date, t.to_date FROM employees e INNER JOIN  dept_emp de ON e.emp_no=de.emp_no INNER JOIN departments d ON de.dept_no=d.dept_no INNER JOIN titles t ON e.emp_no=t.emp_no ORDER BY  e.first_name, e.last_name, d.dept_name, t.from_date;

Production attendue:

489903 rows in set (4.33 sec)

Nous allons désactiver la journalisation générale une fois la requête terminée:

SET GLOBAL general_log=0;

Notez que si vous laissez la connexion ouverte, les requêtes continueront d’être ajoutées au journal, ce qui peut compliquer les tests. Donc, assurez-vous de désactiver le journal juste après avoir terminé votre test. Vérifions que le fichier journal a été créé dans le répertoire:

sudo ls -l /var/lib/mysql/capt*

-rw-rw----. 1 mysql mysql 861 Sep 24 15:09 /var/lib/mysql/capture_queries.log

Copions ce fichier dans notre répertoire de test MySQL. Si vous utilisez un serveur distinct pour le test, copiez-le sur ce serveur.

sudo cp /var/lib/mysql/capture_queries.log /mysqlslap_tutorial/

Il devrait y avoir un peu de données dans ce fichier journal. Dans cet exemple, la requête souhaitée doit être proche de la fin. Vérifiez la dernière partie du fichier:

sudo tail /mysqlslap_tutorial/capture_queries.log

Production attendue:

        6294 Query show databases
        6294 Query show tables
        6294 Field List    departments
        6294 Field List    dept_emp
        6294 Field List    dept_manager
        6294 Field List    employees
        6294 Field List    salaries
        6294 Field List    titles
140930 15:34:52  6294 Query SELECT e.first_name, e.last_name, d.dept_name, t.title, t.from_date, t.to_date FROM employees e INNER JOIN  dept_emp de ON e.emp_no=de.emp_no INNER JOIN departments d ON de.dept_no=d.dept_no INNER JOIN titles t ON e.emp_no=t.emp_no ORDER BY  e.first_name, e.last_name, d.dept_name, t.from_date
140930 15:35:06  6294 Query SET GLOBAL general_log=0

Ce journal affiche les commandes SQL et leurs horodatages. Ce qui nous intéresse, c’est l’instruction SQL vers la fin du fichier. Ce devrait être exactement la même chose que la commande que nous avons exécutée sur la base de données de production, puisque c’est là que nous l’avons capturée.

Dans cet exemple, nous connaissions déjà la requête. Toutefois, dans un environnement de production, cette méthode peut être très utile pour rechercher des requêtes que vous ne connaissez peut-être pas et qui sont exécutées sur votre serveur.

Notez que si vous avez exécuté ou déclenché différentes requêtes lors de la journalisation, ce fichier sera complètement différent. Dans un scénario réel, ce fichier pourrait être inondé de centaines d’entrées provenant de toutes les connexions. Votre objectif est de rechercher la ou les requêtes à l’origine d’un goulot d’étranglement. Vous pouvez commencer par faire une liste de chaque ligne contenant le texte. Ensuite, vous aurez une liste des requêtes qui ont été exécutées sur votre base de données au cours du test.

Pour chaque requête que vous souhaitez tester, copiez-la dans un fichier qui se termine par une extension + .sql +.

Par exemple:

sudo vi /mysqlslap_tutorial/capture_queries.sql

Le contenu devrait être la requête MySQL que vous voulez tester, sans saut de ligne et sans point-virgule à la fin:

SELECT e.first_name, e.last_name, d.dept_name, t.title, t.from_date, t.to_date FROM employees e INNER JOIN  dept_emp de ON e.emp_no=de.emp_no INNER JOIN departments d ON de.dept_no=d.dept_no INNER JOIN titles t ON e.emp_no=t.emp_no ORDER BY  e.first_name, e.last_name, d.dept_name, t.from_date

Ensuite, assurez-vous que les résultats de la requête ne sont pas mis en cache. Retournez à votre * session de test MySQL *. Exécutez la commande suivante:

RESET QUERY CACHE;

Il est maintenant temps d’exécuter l’utilitaire mysqlslap avec le fichier de script. Assurez-vous d’utiliser le nom de fichier de script correct dans le paramètre. Nous n’utiliserons que dix connexions simultanées et répéterons le test deux fois. Exécutez ceci à partir de votre * serveur de test *:

sudo mysqlslap --user=sysadmin --password --host=localhost  --concurrency=10 --iterations=2 --create-schema=employees_backup --query="" --verbose

La sortie de référence ressemble à ceci dans notre système:

Benchmark
       Average number of seconds to run all queries: 68.692 seconds
       Minimum number of seconds to run all queries: 59.301 seconds
       Maximum number of seconds to run all queries: 78.084 seconds
       Number of clients running queries: 10
       Average number of queries per client: 1

Alors, comment pouvons-nous améliorer ce point de référence?

Vous aurez besoin d’une certaine familiarité avec les requêtes MySQL pour évaluer ce qu’elles font.

En regardant en arrière, la requête montre qu’elle effectue plusieurs jointures sur plusieurs tables. La requête affiche l’historique des tâches des employés et, ce faisant, joint différentes tables en fonction du champ. Elle utilise également le champ pour s’inscrire, mais comme il n’ya que quelques enregistrements de département, nous l’ignorerons. Comme la base de données contient de nombreuses entrées, il est logique de supposer que la création d’index sur le champ pourrait améliorer la requête.

Avec un peu de pratique, une fois que vous aurez localisé les requêtes qui taxent le serveur (c’est la partie aidée par mysqlslap!), Vous serez en mesure d’évaluer ces requêtes en fonction de votre connaissance de MySQL et de votre base de données.

Ensuite, vous pouvez essayer d’améliorer votre base de données ou les requêtes qui y sont exécutées.

Dans notre cas, ajoutons les index mentionnés ci-dessus. Nous allons créer trois index sur. Un index sera créé sur le champ de la table, un autre index sera créé sur le champ de la table et le dernier sera créé sur le champ de la table.

Voyons notre session de test MySQL et exécutons les commandes suivantes:

USE employees_backup;

CREATE INDEX employees_empno ON employees(emp_no);

CREATE INDEX dept_emp_empno ON dept_emp(emp_no);

CREATE INDEX titles_empno ON titles(emp_no);

Pour revenir à notre fenêtre de terminal principale sur le serveur de test, si nous exécutons mysqlslap avec les mêmes paramètres, nous verrons une différence dans le test:

sudo mysqlslap --user=sysadmin --password --host=localhost  --concurrency=10 --iterations=2 --create-schema=employees_backup --query="/mysqlslap_tutorial/capture_queries.sql" --verbose
Benchmark
       Average number of seconds to run all queries: 55.869 seconds
       Minimum number of seconds to run all queries: 55.706 seconds
       Maximum number of seconds to run all queries: 56.033 seconds
       Number of clients running queries: 10
       Average number of queries per client: 1

Nous pouvons voir qu’il y a une amélioration immédiate du temps moyen, minimum et maximum pour exécuter la requête. Au lieu d’une moyenne de 68 secondes, la requête s’exécute maintenant en 55 secondes. C’est une amélioration de 13 secondes pour le même chargement.

Étant donné que cette modification de base de données a produit de bons résultats dans l’environnement de test, vous pouvez maintenant envisager de la déployer sur votre serveur de base de données de production, mais gardez à l’esprit que les modifications de base de données présentent généralement des avantages et des inconvénients.

Vous pouvez répéter le processus de test des commandes et des améliorations avec toutes les requêtes que vous avez extraites de votre journal.

Dépannage - mysqlslap n’affiche pas la sortie

Si vous exécutez une commande de test et n’obtenez aucune sortie, c’est une bonne indication que les ressources de votre serveur risquent d’être utilisées au maximum. Les symptômes peuvent inclure un manque de sortie ou une erreur du type + mysqlslap: Erreur lors de l’enregistrement du résultat: 2013 Connexion perdue avec le serveur MySQL lors de l’interrogation +.

Vous voudrez peut-être réessayer le test avec un nombre plus petit dans le paramètre ou. Vous pouvez également essayer de mettre à niveau votre environnement de serveur de test.

Cela peut être un bon moyen de déterminer les limites extérieures de la capacité de votre serveur de base de données.

Conclusion

mysqlslap est un outil simple, léger, facile à utiliser et qui s’intègre nativement au moteur de base de données MySQL. Il est disponible pour toutes les éditions de MySQL à partir de la version 5.1.4.

Dans ce tutoriel, nous avons vu comment utiliser mysqlslap avec ses différentes options et manipulé avec un exemple de base de données. Vous pouvez télécharger d’autres exemples de bases de données à partir du site MySQL et vous exercer également à les utiliser. Comme nous l’avons déjà mentionné, * n’effectuez pas de tests sur un serveur de base de données de production. *

Le dernier cas d’utilisation de ce didacticiel impliquait une seule requête. Bien que nous ayons quelque peu amélioré les performances de cette requête en ajoutant des index supplémentaires aux trois tables, le processus n’est peut-être pas si simple en réalité. L’ajout d’index supplémentaires peut parfois dégrader les performances du système et les administrateurs de base de données doivent souvent peser les avantages de l’ajout d’un index supplémentaire au coût en termes de performances qu’il peut impliquer.

Les scénarios de test dans la vie réelle sont plus complexes, mais cela devrait vous donner les outils pour commencer à tester et améliorer les performances de votre base de données.