Mysql
 sql >> Base de données >  >> RDS >> Mysql

Analyse comparative des performances MySQL :MySQL 5.7 contre MySQL 8.0

MySQL 8.0 a apporté d'énormes changements et modifications qui ont été poussés par l'équipe Oracle MySQL. Les fichiers physiques ont été modifiés. Par exemple, *.frm, *.TRG, *.TRN et *.par n'existent plus. Des tonnes de nouvelles fonctionnalités ont été ajoutées telles que CTE (Common Table Expressions), Window Functions, Invisible Indexes, regexp (ou Regular Expression) - cette dernière a été modifiée et fournit désormais une prise en charge complète d'Unicode et est sécurisée sur plusieurs octets. Le dictionnaire de données a également changé. Il est maintenant intégré à un dictionnaire de données transactionnelles qui stocke des informations sur les objets de la base de données. Contrairement aux versions précédentes, les données du dictionnaire étaient stockées dans des fichiers de métadonnées et des tables non transactionnelles. La sécurité a été améliorée avec le nouvel ajout de caching_sha2_password qui est désormais l'authentification par défaut en remplacement de mysql_native_password et offre plus de flexibilité mais une sécurité renforcée qui doit utiliser soit une connexion sécurisée, soit une connexion non chiffrée prenant en charge l'échange de mots de passe à l'aide d'une paire de clés RSA.

Avec toutes ces fonctionnalités, améliorations et améliorations intéressantes offertes par MySQL 8.0, notre équipe était intéressée à déterminer les performances de la version actuelle de MySQL 8.0, d'autant plus que notre prise en charge des versions MySQL 8.0.x dans ClusterControl est en cours (alors restez à l'écoute sur ce). Ce billet de blog ne discutera pas des fonctionnalités de MySQL 8.0, mais vise à évaluer ses performances par rapport à MySQL 5.7 et à voir comment il s'est amélioré ensuite.

Configuration et environnement du serveur

Pour ce benchmark, j'ai l'intention d'utiliser une configuration minimale pour la production en utilisant l'environnement AWS EC2 suivant :

Type d'instance :instance t2.xlarge
Stockage :gp2 (stockage SSD avec un minimum de 100 et un maximum de 16 000 IOPS)
vCPUS :4
Mémoire :16 Gio
Version MySQL 5.7 :MySQL Community Server (GPL) 5.7.24
Version MySQL 8.0 :MySQL Community Server - GPL 8.0.14

J'ai également défini quelques variables notables pour ce benchmark, à savoir :

  • innodb_max_dirty_pages_pct =90 ## C'est la valeur par défaut dans MySQL 8.0. Voir ici pour plus de détails.
  • innodb_max_dirty_pages_pct_lwm=10 ## C'est la valeur par défaut dans MySQL 8.0
  • innodb_flush_neighbors=0
  • innodb_buffer_pool_instances=8
  • innodb_buffer_pool_size=8Gio

Le reste des variables définies ici pour les deux versions (MySQL 5.7 et MySQL 8.0) sont déjà configurées par ClusterControl pour son modèle my.cnf.

De plus, l'utilisateur que j'ai utilisé ici n'est pas conforme à la nouvelle authentification de MySQL 8.0 qui utilise caching_sha2_password. Au lieu de cela, les deux versions de serveur utilisent mysql_native_password plus la variable innodb_dedicated_server est désactivée (par défaut), qui est une nouvelle fonctionnalité de MySQL 8.0.

Pour faciliter la vie, j'ai configuré le nœud de la version communautaire MySQL 5.7 avec ClusterControl à partir d'un hôte séparé, puis supprimé le nœud dans un cluster et arrêté l'hôte ClusterControl pour rendre le nœud MySQL 5.7 inactif (pas de surveillance du trafic). Techniquement, les deux nœuds MySQL 5.7 et MySQL 8.0 sont inactifs et aucune connexion active ne passe par les nœuds, il s'agit donc essentiellement d'un test d'analyse comparative.

Commandes et scripts utilisés

Pour cette tâche, sysbench est utilisé pour les tests et la simulation de charge pour les deux environnements. Voici les commandes ou scripts suivants utilisés pour ce test :

sb-prepare.sh

#!/bin/bash

host=$1
#host192.168.10.110
port=3306
user='sysbench'
password='[email protected]'
table_size=500000
rate=20
ps_mode='disable'
sysbench /usr/share/sysbench/oltp_read_write.lua --db-driver=mysql --threads=1 --max-requests=0 --time=3600 --mysql-host=$host --mysql-user=$user --mysql-password=$password --mysql-port=$port --tables=10 --report-interval=1 --skip-trx=on --table-size=$table_size --rate=$rate --db-ps-mode=$ps_mode prepare

sb-run.sh

#!/usr/bin/env bash

host=$1
port=3306
user="sysbench"
password="[email protected]"
table_size=100000
tables=10
rate=20
ps_mode='disable'
threads=1
events=0
time=5
trx=100
path=$PWD

counter=1

echo "thread,cpu" > ${host}-cpu.csv

for i in 16 32 64 128 256 512 1024 2048; 
do 

    threads=$i

    mysql -h $host -e "SHOW GLOBAL STATUS" >> $host-global-status.log
    tmpfile=$path/${host}-tmp${threads}
    touch $tmpfile
    /bin/bash cpu-checker.sh $tmpfile $host $threads &

    /usr/share/sysbench/oltp_read_write.lua --db-driver=mysql --events=$events --threads=$threads --time=$time --mysql-host=$host --mysql-user=$user --mysql-password=$password --mysql-port=$port --report-interval=1 --skip-trx=on --tables=$tables --table-size=$table_size --rate=$rate --delete_inserts=$trx --order_ranges=$trx --range_selects=on --range-size=$trx --simple_ranges=$trx --db-ps-mode=$ps_mode --mysql-ignore-errors=all run | tee -a $host-sysbench.log

    echo "${i},"`cat ${tmpfile} | sort -nr | head -1` >> ${host}-cpu.csv
    unlink ${tmpfile}

    mysql -h $host -e "SHOW GLOBAL STATUS" >> $host-global-status.log
done

python $path/innodb-ops-parser.py $host

mysql -h $host -e "SHOW GLOBAL VARIABLES" >> $host-global-vars.log

Ainsi, le script prépare simplement le schéma sbtest et remplit les tables et les enregistrements. Ensuite, il effectue des tests de charge en lecture/écriture à l'aide du script /usr/share/sysbench/oltp_read_write.lua. Le script vide l'état global et les variables MySQL, collecte l'utilisation du processeur et analyse les opérations de ligne InnoDB gérées par le script innodb-ops-parser.py. Les scripts génèrent ensuite des fichiers *.csv basés sur les journaux de vidage qui ont été collectés pendant le benchmark, puis j'ai utilisé une feuille de calcul Excel ici pour générer le graphique à partir de fichiers *.csv. Veuillez vérifier le code ici dans ce référentiel github.

Passons maintenant aux résultats du graphique !

Opérations sur les lignes InnoDB

Fondamentalement, ici, j'ai uniquement extrait les opérations de ligne InnoDB qui effectuent les sélections (lectures), les suppressions, les insertions et les mises à jour. Lorsque le nombre de threads augmente, MySQL 8.0 surpasse considérablement MySQL 5.7 ! Les deux versions n'ont pas de changements de configuration spécifiques, mais seulement les variables notables que j'ai définies. Les deux versions utilisent donc à peu près les valeurs par défaut.

Fait intéressant, en ce qui concerne les affirmations de l'équipe MySQL Server concernant les performances de lecture et d'écriture dans la nouvelle version, les graphiques indiquent une amélioration significative des performances, en particulier dans un serveur à forte charge. Imaginez la différence entre MySQL 5.7 et MySQL 8.0 pour toutes ses opérations de ligne InnoDB, il y a une grande différence, surtout lorsque le nombre de threads augmente. MySQL 8.0 révèle qu'il peut fonctionner efficacement quelle que soit sa charge de travail.

Transactions traitées

Comme le montre le graphique ci-dessus, les performances de MySQL 8.0 montrent à nouveau une énorme différence dans le temps nécessaire au traitement des transactions. Plus il est bas, plus il est performant, ce qui signifie qu'il est plus rapide de traiter les transactions. Les transactions traitées (le deuxième graphique) révèlent également que les deux nombres de transactions ne diffèrent pas l'un de l'autre. Cela signifie que les deux versions exécutent presque le même nombre de transactions mais diffèrent par la vitesse à laquelle elles peuvent se terminer. Bien que je puisse dire que MySQL 5.7 peut encore gérer beaucoup de choses à faible charge, mais la charge réaliste, en particulier en production, pourrait être plus élevée, en particulier pendant la période la plus chargée.

Le graphique ci-dessus montre toujours les transactions qu'il a pu traiter mais sépare la lecture des écritures. Cependant, il y a en fait des valeurs aberrantes dans les graphiques que je n'ai pas incluses car ce sont de minuscules morceaux du résultat qui fausseraient le graphique.

MySQL 8.0 révèle de grandes améliorations, notamment pour les lectures. Il affiche son efficacité en écriture notamment pour les serveurs à forte charge de travail. Un excellent support supplémentaire qui a un impact sur les performances de MySQL pour les lectures dans la version 8.0 est la possibilité de créer un index dans l'ordre décroissant (ou des analyses d'index vers l'avant). Les versions précédentes n'avaient qu'un balayage d'index ascendant ou descendant, et MySQL devait effectuer un tri de fichiers s'il avait besoin d'un ordre décroissant (si un tri de fichiers est nécessaire, vous pouvez envisager de vérifier la valeur de max_length_for_sort_data). Les index décroissants permettent également à l'optimiseur d'utiliser des index multi-colonnes lorsque l'ordre de parcours le plus efficace mélange l'ordre croissant pour certaines colonnes et l'ordre décroissant pour d'autres. Voir ici pour plus de détails.

Ressources processeur

Au cours de cette analyse comparative, j'ai décidé de prendre certaines ressources matérielles, notamment l'utilisation du processeur.

Permettez-moi d'abord d'expliquer comment je prends la ressource CPU ici lors de l'analyse comparative. sysbench n'inclut pas de statistiques collectives pour les ressources matérielles utilisées ou utilisées pendant le processus lorsque vous comparez une base de données. Pour cette raison, ce que j'ai fait est de créer un indicateur en créant un fichier, de me connecter à l'hôte cible via SSH, puis de récolter les données de la commande Linux "top" et de les analyser en dormant pendant une seconde avant de les collecter à nouveau. Après cela, prenez l'augmentation la plus remarquable de l'utilisation du processeur pour le processus mysqld, puis supprimez le fichier d'indicateur. Vous pouvez consulter le code que j'ai dans github.

Alors revenons sur le résultat du graphique, il semble révéler que MySQL 8.0 consomme beaucoup de CPU. Plus que MySQL 5.7. Cependant, il peut avoir à gérer de nouvelles variables ajoutées dans MySQL 8.0. Par exemple, ces variables peuvent avoir un impact sur votre serveur MySQL 8.0 :

  • innodb_log_spin_cpu_abs_lwm =80
  • innodb_log_spin_cpu_pct_hwm =50
  • innodb_log_wait_for_flush_spin_hwm =400
  • innodb_parallel_read_threads =4

Les variables avec ses valeurs sont laissées par ses valeurs par défaut pour ce benchmark. Les trois premières variables gèrent le processeur pour la journalisation redo, ce qui dans MySQL 8.0 a été une amélioration en raison de la refonte de la façon dont InnoDB écrit dans le journal REDO. La variable innodb_log_spin_cpu_pct_hwm a une affinité CPU, ce qui signifie qu'elle ignorerait les autres cœurs CPU si mysqld n'est épinglé qu'à 4 cœurs, par exemple. Pour les threads de lecture parallèles, dans MySQL 8.0, il ajoute une nouvelle variable pour laquelle vous pouvez régler le nombre de threads à utiliser.

Cependant, je n'ai pas approfondi le sujet. Il existe des moyens d'améliorer les performances en tirant parti des fonctionnalités offertes par MySQL 8.0.

Conclusion

Il y a des tonnes d'améliorations présentes dans MySQL 8.0. Les résultats du benchmark révèlent qu'il y a eu une amélioration impressionnante, non seulement sur la gestion des charges de travail en lecture, mais également sur une charge de travail élevée en lecture/écriture par rapport à MySQL 5.7.

En ce qui concerne les nouvelles fonctionnalités de MySQL 8.0, il semble qu'il ait tiré parti des technologies les plus récentes non seulement sur les logiciels (comme une grande amélioration pour Memcached, la gestion à distance pour un meilleur travail DevOps, etc.) mais également en quincaillerie. Prenons par exemple le remplacement de latin1 par UTF8MB4 comme encodage de caractères par défaut. Cela signifierait qu'il faudrait plus d'espace disque puisque UTF8 a besoin de 2 octets sur les caractères non-US-ASCII. Bien que ce benchmark n'ait pas tiré parti de l'utilisation de la nouvelle méthode d'authentification avec caching_sha2_password, cela n'affectera pas les performances s'il utilise le chiffrement. Une fois authentifié, il est stocké dans le cache, ce qui signifie que l'authentification n'est effectuée qu'une seule fois. Donc, si vous utilisez un seul utilisateur pour votre client, ce ne sera pas un problème et il est plus sécurisé que les versions précédentes.

Étant donné que MySQL exploite le matériel et les logiciels les plus récents, il modifie ses variables par défaut. Vous pouvez lire ici pour plus de détails.

Dans l'ensemble, MySQL 8.0 a dominé efficacement MySQL 5.7.