Savez-vous vraiment comment utiliser EXPLAIN, le chemin vers le roi de l'optimisation des performances SQL

Répertoire de colonnes des nouvelles fonctionnalités de MySQL 8.0

Savez-vous vraiment utiliser EXPLAIN, l'optimisation des performances SQL, le chemin de la promotion du roi,
l'index descendant et l'index invisible des Trois Mousquetaires sont
très attendus, MySQL 8.0 Index Fonctionnel
double mot de passe des Trois Mousquetaires, MySQL 8.0 fonctionnalité innovante
compatibilité sql_mode , la mise à niveau de MySQL 8.0 a marché sur la fosse pour
être attentif aux changements de paramètres, la mise à niveau de MySQL 8.0 pour éviter de marcher à nouveau sur la fosse



avant-propos

En tant que base de données la plus populaire au monde, MySQL compte d'innombrables praticiens et on peut dire qu'au moins neuf programmeurs sur dix ont utilisé MySQL. Les développeurs MySQL ou les DBA utilisent souvent l'instruction EXPLAIN pour afficher le plan d'exécution SQL. Il existe de nombreux articles sur l'interprétation d'EXPLAIN, et chaque développeur a sa propre compréhension des résultats d'EXPLAIN. Cependant, utiliseriez-vous vraiment EXPLAIN ?

1. Les joueurs Bronze utilisent EXPLAIN - EXPLAIN

Prenons la requête sur la table de test sysbench sbtest1comme exemple pour voir comment tout le monde utilise EXPLAIN.

# 测试表
Create Table: CREATE TABLE `sbtest1` (
  `id` int NOT NULL AUTO_INCREMENT,
  `k` int NOT NULL DEFAULT '0',
  `c` char(120) NOT NULL DEFAULT '',
  `pad` char(60) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`),
  KEY `idx_k` (`k`) /*!80000 INVISIBLE */,
  KEY `idx_c`(`c`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1

sbtest1Il y a deux index secondaires idx_ksum sur la table idx_c, exécutez le SQL suivant : select pad from sbtest1 where c = '64613629' and k = 64613629;

Les joueurs Bronze l'utilisent généralement directement pour explain select ...visualiser le plan d'exécution de SQL.

MySQL [sbtest]> explain select pad from sbtest1 where c = '64613629' and k = 64613629;
+----+-------------+---------+------------+------+---------------+-------+---------+-------+------+----------+-------------+
| id | select_type | table   | partitions | type | possible_keys | key   | key_len | ref   | rows | filtered | Extra       |
+----+-------------+---------+------------+------+---------------+-------+---------+-------+------+----------+-------------+
|  1 | SIMPLE      | sbtest1 | NULL       | ref  | idx_c   | idx_c | 120     | const |    1 |     5.00 | Using where |
+----+-------------+---------+------------+------+---------------+-------+---------+-------+------+----------+-------------+
1 row in set, 1 warning (0.01 sec)

Selon la sortie d'EXPLAIN, nous pouvons voir que le plan d'exécution de cette requête SQL est idx_cun parcours d'index de l'index secondaire.

Ainsi, lorsque le SQL réel est exécuté, cet index est-il vraiment EXPLAINutilisé comme indiqué idx_c?


2. Les joueurs Platinum utilisent EXPLAIN - EXPLAIN FOR CONNECTION

Pour l'exemple de la table de test ci-dessus , nous ne savons pas s'il faut utiliser idx_kou indexer dans l'exécution réelle.idx_c

Ensuite, il existe un moyen de connaître la sélection d'index lorsque le SQL est réellement exécuté.

Ici, nous introduisons une utilisation avancée de EXPLAIN - explain for connection. explain for connectionVous pouvez afficher le plan d'exécution du SQL dans la session d'exécution.

Toujours en prenant la table de test ci-dessus comme exemple, nous exécutons d'abord SQL dans la session 1.

# Session 1
MySQL [sbtest]> select pad from sbtest1 where c = 64613629 and k = '64613629';

Ensuite, ouvrez une autre session 2 et affichez le SQL en cours d'exécution et le PROCESSID correspondant dans la session 2.

# Session 2
MySQL [sbtest]> show processlist;
+----------+------------+----------------------+--------+------------------+---------+---------------------------------------------------------------+--------------------------------------------+
| Id       | User       | Host                 | db     | Command          | Time    | State                                                         | Info                                       |
+----------+------------+----------------------+--------+------------------+---------+---------------------------------------------------------------+--------------------------------------------+
| 20255132 | wang       | 127.0.0.1:57932      | sbtest | Query            |       0 | init                                                          | show processlist                           |
| 20264939 | wang       | 127.0.0.1:50656      | sbtest | Query            |       5 | executing                                                     | select pad from sbtest1 where c = 64613629 and k = '64613629' |
+----------+------------+----------------------+--------+------------------+---------+---------------------------------------------------------------+--------------------------------------------+

Enfin, selon le numéro de thread affiché par show processlist, utilisez pour explain for connection {PROCESSID}visualiser le plan d'exécution SQL de la session 1. On peut voir que le plan d'exécution de la session 1 est en fait un parcours complet de la table, et non idx_cun parcours d'index ci-dessus.

# Session 2
MySQL [sbtest]> explain for connection 20264939;
+----+-------------+---------+------------+------+---------------+------+---------+------+----------+----------+-------------+
| id | select_type | table   | partitions | type | possible_keys | key  | key_len | ref  | rows     | filtered | Extra       |
+----+-------------+---------+------------+------+---------------+------+---------+------+----------+----------+-------------+
|  1 | SIMPLE      | sbtest1 | NULL       | ALL  | idx_c         | NULL | NULL    | NULL | 93776256 |   100.00 | Using where |
+----+-------------+---------+------------+------+---------------+------+---------+------+----------+----------+-------------+

Permet explain for connectiond'afficher le plan d'exécution SQL pour la session spécifiée. De cette façon, vous pouvez voir le plan d'exécution du SQL en cours d'exécution . Avec cet artefact, nous pouvons vérifier plus directement le plan d'exécution SQL.

Cependant, en supposant que la durée d'exécution SQL de la session 1 est très courte, ou qu'il y a trop de connexions en cours dans la base de données, il n'est pas facile de trouver la connexion pour le SQL spécifié et de visualiser son plan d'exécution.

Pour aller plus loin, nous avons besoin d'un moyen plus intuitif et efficace de visualiser les plans d'exécution.


3. Les joueurs Diamond utilisent EXPLAIN - EXPLAIN ANALYZE

Une nouvelle forme d'instruction EXPLAIN a été introduite dans MySQL 8.0.18 - EXPLAIN ANALYZE. EXPLAIN ANALYZELe coût estimé et le coût réel de chaque étape du plan d'exécution SQL peuvent être affichés sous forme d'arborescence. C'est-à-dire que EXPLAIN ANALYZEle coût d'exécution de SQL sera estimé sur la base des informations statistiques, puis le SQL sera réellement exécuté, puis le coût d'exécution réel du SQL sera affiché avec le nombre d'appels à chaque étape, le nombre de lignes renvoyées et d'autres informations. Nous pouvons comparer l'exécution estimée et réelle et avoir une compréhension complète du plan d'exécution SQL.

Ou prenez la requête de la table de test ci-dessus comme exemple, vérifions EXPLAIN ANALYZEsi elle est vraiment si magique.

# explain analyze查看实际执行计划
MySQL [sbtest]> explain analyze select pad from sbtest1 where c = 64613629 and k = '64613629';
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| EXPLAIN                                                                                                                                                                                                                                           |
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| -> Filter: ((sbtest1.c = 64613629) and (sbtest1.k = 64613629))  (cost=100959.75 rows=9938) (actual time=0.046..344.477 rows=1 loops=1)
    -> Table scan on sbtest1  (cost=100959.75 rows=993820) (actual time=0.041..243.610 rows=1000000 loops=1)
 |
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.35 sec)

Comme vous pouvez le voir, la sortie est très différente de EXPLAIN ANALYZEla sortie précédente . Dans MySQL 8.0, le format de sortie a été EXPLAINintroduit afin d'afficher plus clairement le plan d'exécution . format=tree(En fait, il existe un autre format=jsonformat de sortie introduit en même temps, ce qui est très utile pour traiter les résultats de sortie dans les programmes)

Le plan d'exécution du format de sortie arborescent, l'ordre de lecture respecte deux principes :

  1. Les lignes avec une plus grande indentation sont exécutées en premier ;
  2. Les lignes avec la même indentation sont exécutées de haut en bas.

Dans cet exemple, la deuxième ligne avec un grand retrait est exécutée en premier : Table scan on sbtest1, c'est-à-dire qu'un balayage complet de la table est effectué sur sbtest1 ; le coût d'exécution estimé est de 100 959,75 dans la première parenthèse et le nombre estimé de lignes renvoyées est de 993 820 ; le la deuxième parenthèse montre le temps réel = 0,041…243,610 signifie que le temps d'exécution pour obtenir la première ligne est de 0,041 ms, et le temps pour obtenir toutes les lignes est de 243,610 ms ( notez que si la boucle est exécutée plusieurs fois, cela signifie que le temps moyen pour obtenir toutes les lignes à chaque fois ), le nombre réel de lignes renvoyées est de 100w et la boucle est répétée une fois.

Exécutez ensuite la première ligne avec un retrait plus petit : Filter, filtrez le jeu de résultats, la première parenthèse indique que le coût d'exécution estimé est de 100 959,75 et que le nombre estimé de lignes renvoyées est de 9 938 ; la deuxième parenthèse indique l'exécution réelle, temps réel=0,046 … 344,477 signifie que le temps d'exécution pour obtenir la première ligne est de 0,046 ms, le temps pour obtenir toutes les lignes est de 344,477 ms, le nombre réel de lignes renvoyées est de 1 ligne et la boucle est de 1 fois. ( Notez que le temps de retour de toutes les lignes correspondant à une ligne moins indentée inclut le temps de retour de la ligne la plus indentée en dessous ).

EXPLAIN ANALYZELa dernière étape ci-dessus montre que le temps d'exécution réel de ce SQL est de 344,477 ms, c'est-à-dire que le temps d'exécution total est d'environ 0,35 s ( 1 row in set (0.35 sec)conformément au temps d'exécution SQL renvoyé par MySQL).

Alors, EXPLAIN ANALYZEest-ce que le temps d'exécution réel est affiché, est-ce le temps d'exécution réel de ce SQL ? En fait, ce n'est pas le cas.

Exécutons en fait ce SQL pour voir le temps d'exécution spécifique.

# 实际执行SQL,查看执行时间
MySQL [sbtest]> select pad from sbtest1 where c = 64613629 and k = '64613629';
+-------------------------------------------------------------+
| pad                                                         |
+-------------------------------------------------------------+
| 22195207048-70116052123-74140395089-76317954521-98694025897 |
+-------------------------------------------------------------+
1 row in set (0.29 sec)

On peut voir que le temps d'exécution réel de SQL est de 0,29 s, ce qui est plus court que EXPLAIN ANALYZEles 0,35 s indiqués dans , soit une différence de 20 %. Oui, EXPLAIN ANALYZEle traçage de l'exécution réelle de SQL entraîne naturellement une surcharge supplémentaire. EXPLAIN ANALYZELa surcharge d'exécution est encore un peu importante, ici j'espère que l'officiel pourra l'optimiser à nouveau.

Dans tous les cas, l'introduction de MySQL 8.0 EXPLAIN ANALYZEnous montre clairement le coût d'exécution estimé et la consommation d'exécution réelle de SQL, ce qui est d'une grande valeur pour optimiser les performances SQL.

Vous ne pouvez pas vraiment utiliser EXPLAIN sans utiliser l'analyse EXPLAIN de MySQL 8.0 !


4. Le roi le plus fort utilise EXPLAIN - OPTIMIZER_TRACE

EXPLAINAvec les différentes postures d'utilisation introduites précédemment , EXPLAINnous pouvons bien gérer l'optimisation des performances SQL avec de bons outils. Enfin, nous introduisons un EXPLAINmoyen de visualiser le plan d'exécution de l'optimiseur sans l'utiliser, le roi le plus fort de l'optimisation des performances - optimizer_trace.

optimizer_traceLe processus de prise de décision et d'exécution de l'optimiseur MySQL peut être enregistré et sauvegardé dans la table INFORMATION_SCHEMA.OPTIMIZER_TRACE au format JSON, afin que les DBA et les développeurs puissent comprendre en profondeur l'ensemble du processus de prise de décision de l'optimiseur.

Ou utilisez le test SQL ci-dessus, testons-le et vérifions-le.

# 1.打开optimizer_trace
SET optimizer_trace="enabled=on";

# 2. 执行测试SQL
select pad from sbtest1 where c = 64613629 and k = '64613629';

# 查看INFORMATION_SCHEMA.OPTIMIZER_TRACE表
SELECT * FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;

# 关闭optimizer_trace
SET optimizer_trace="enabled=off";

INFORMATION_SCHEMA.OPTIMIZER_TACERLe contenu du tableau est très long, et la partie décisionnelle de l'interception est la suivante :

# optimizer_trace的部分输出
{
						"considered_execution_plans": [{
							"plan_prefix": [],
							"table": "`sbtest1`",
							"best_access_path": {
								"considered_access_paths": [{
									"rows_to_scan": 993820,
									"access_type": "scan",
									"resulting_rows": 993820,
									"cost": 100960,
									"chosen": true
								}]
							},
							"condition_filtering_pct": 100,
							"rows_for_plan": 993820,
							"cost_for_plan": 100960,
							"chosen": true
					

optimizer_traceCe tueur ultime peut être utilisé lorsque le plan d'exécution SQL est incompatible avec nos résultats attendus . Étant donné que le SQL exécuté dans MySQL n'est pas compliqué en réalité, cet outil au niveau de l'arme nucléaire n'est généralement pas utilisé.


Résumer

Cet article présente plusieurs façons de visualiser le processus d'exécution de l'optimiseur SQL : EXPLAIN, EXPLAIN FOR CONNECTION, EXPLAIN ANALYZE, OPTIMIZER_TRACE, pour aider les développeurs à surmonter les obstacles sur la voie de l'optimisation des performances SQL, des joueurs de bronze aux rois de l'auto-amélioration.

喜欢的同学麻烦点个关注和点赞

Je suppose que tu aimes

Origine blog.csdn.net/wangzihuacool/article/details/124371738
conseillé
Classement