[Optimisation lente des performances SQL] Le cycle de vie d'un SQL


1. Le processus d'exécution d'un simple SQL dans MySQL

Un diagramme simple illustre les composants de l'architecture MySQL et les relations entre eux. Ensuite, j'utiliserai des instructions SQL pour l'analyser.

Par exemple, l'instruction SQL suivante

  
  
  
  
  
SELECT department_id FROM employee WHERE name = 'Lucy' AND age > 18 GROUP BY department_id

Le nom est l'index. Analysons-le par ordre chronologique.

1. Client : Tel que l'outil de ligne de commande MySQL, Navicat, DBeaver ou d'autres applications pour envoyer des requêtes SQL au serveur MySQL.

2. Connecteur : Responsable de l'établissement des connexions avec les clients, de la gestion des connexions et du maintien des connexions. Lorsqu'un client se connecte à un serveur MySQL , le connecteur vérifie le nom d'utilisateur et le mot de passe du client, puis alloue un thread pour gérer la demande du client.

3. Cache de requêtes : Le cache de requêtes est utilisé pour mettre en cache les requêtes précédemment exécutées et leurs résultats. Lorsqu'une nouvelle requête de requête est reçue, MySQL vérifie d'abord si la même requête et ses résultats existent déjà dans le cache de requêtes. S'il y a des résultats de requête correspondants dans le cache de requêtes, MySQL renverra directement les résultats mis en cache sans réexécuter la requête. Cependant, s'il n'y a aucun résultat de requête correspondant dans le cache de requêtes, MySQL continuera à exécuter la requête.
4. Analyseur :
  • Analysez l'instruction de requête et vérifiez la syntaxe.
  • Vérifiez que les noms de table et de colonne sont corrects.
  • Générer un arbre de requête.
5. Optimiseur : analysez l'arborescence des requêtes, envisagez différents plans d'exécution, estimez les coûts des différents plans d'exécution et sélectionnez le meilleur plan d'exécution. Dans cet exemple, l'optimiseur peut choisir d'utiliser le nom index pour la requête car nom est la colonne d'index.
6. Exécuteur : Selon le plan d'exécution sélectionné par l'optimiseur, envoyer une requête au moteur de stockage pour obtenir des lignes de données répondant aux conditions.
7. Moteur de stockage (tel que InnoDB ) :
  • Responsable de l'exécution réelle des analyses d'index, telles que l'exécution de requêtes équivalentes sur l'index de nom de la table des employés. L'interrogation de toutes les colonnes implique de revenir à la table et d'accéder au disque.
  • Avant d'accéder au disque, vérifiez d'abord si la page de données requise existe déjà dans le pool de tampons InnoDB (Buffer Pool). S'il existe des pages de données qualifiées dans le pool de mémoire tampon, les données mises en cache sont utilisées directement. Si la page de données requise ne se trouve pas dans le pool de mémoire tampon, chargez la page de données du disque dans le pool de mémoire tampon.
8.Actionneur :
  • Pour chaque enregistrement trouvé, déterminez à nouveau si l'enregistrement satisfait au nom de la condition d'index. En effet, la page de données chargée dans la mémoire en fonction de la condition d'index peut également contenir des enregistrements qui ne remplissent pas la condition d'index, la condition de nom doit donc être évaluée à nouveau. Si la condition de nom est remplie, la condition de filtre âge > 18 sera continuent d'être jugés.
  • Regroupez les enregistrements qui remplissent la condition en fonction de Department_id.
  • L'exécuteur renvoie l'ensemble de résultats traités au client.
Tout au long de l'exécution de la requête, ces composants fonctionnent ensemble pour exécuter la requête efficacement. Le client est responsable de l'envoi de la requête, le connecteur gère la connexion client, le cache de requêtes tente de réutiliser les résultats de la requête précédente, l'analyseur est responsable de l'analyse de la requête, l'optimiseur sélectionne le meilleur plan d'exécution, l'exécuteur exécute le plan sélectionné par l'optimiseur, le moteur de stockage (tel qu'InnoDB) Responsable de la gestion du stockage et de l'accès aux données. La synergie de ces composants permet à MySQL d'exécuter efficacement des requêtes et de renvoyer des ensembles de résultats.
L'opération de chargement de pages de données d'index dans la mémoire selon les conditions de filtre de colonne d'index est effectuée par le moteur de stockage. Après le chargement en mémoire, l'exécuteur jugera les conditions de filtrage des colonnes d'index et des colonnes non-index.

2. Interrogez l'ordre d'exécution des mots-clés SQL

La séquence d'exécution est la suivante :
1. Fonctionnement du moteur de stockage
(1) FROM : table de données utilisée pour interroger SQL. L'exécuteur obtiendra les données des tables pertinentes du moteur de stockage selon le plan d'exécution sélectionné par l'optimiseur.
(2) ON : utilisé avec JOIN pour spécifier les conditions de connexion. L'exécuteur obtiendra des enregistrements correspondant aux conditions du moteur de stockage selon les conditions données par ON. Si la condition de jointure implique une colonne indexée, le moteur de stockage utilisera l'index pour l'optimisation.
(3) JOIN : spécifiez la méthode de connexion entre les tables (telle que INNER JOIN, LEFT JOIN, etc.). L'exécuteur obtiendra les données de la table de connexion du moteur de stockage selon le plan d'exécution sélectionné par l'optimiseur. Ensuite, l'exécuteur traite la connexion de données en fonction du type de connexion JOIN et des conditions de connexion ON.
(4) OÙ : l'exécuteur filtre les données renvoyées par le moteur de stockage et ne conserve que les enregistrements qui répondent aux conditions de la clause WHERE. Si la condition de filtre a un index, la couche du moteur de stockage le filtrera via l'index et le renverra.
2. Opérations sur les jeux de résultats renvoyés
(5) GROUP BY : l'exécuteur regroupe les enregistrements qui répondent à la condition WHERE en fonction des colonnes spécifiées par GROUP BY.
(6) HAVING : Après avoir exécuté le regroupement, l'exécuteur filtre à nouveau les enregistrements groupés en fonction de la condition HAVING.
(7) SELECT : l'exécuteur obtient les résultats de la requête en fonction du plan d'exécution et des colonnes spécifiées sélectionnées par l'optimiseur.
(8) DISTINCT : l'exécuteur déduplique les résultats de la requête et ne renvoie que les enregistrements uniques.
(9) ORDER BY : l'exécuteur trie les résultats de la requête en fonction des colonnes spécifiées dans la clause ORDER BY.
(10) LIMIT : l'exécuteur tronque les résultats de la requête selon les restrictions spécifiées dans la clause LIMIT et ne renvoie qu'une partie des enregistrements.
3. Le processus d'exécution de la requête d'association de table SQL dans MySQL
  
  
  
  
  
SELECT s.id, s.name, s.age, es.subject, es.score FROM employee s JOIN employee_score es ON s.id = es.employee_id WHERE s.age >18 AND es.subject_id =3 AND es.score >80;
Dans cet exemple, subject_id et score sont des index communs et age est l'index. Analysons- le par ordre chronologique
1. Connecteur : Lorsqu'un client se connecte au serveur MySQL , le connecteur se charge d'établir et de gérer la connexion. Il vérifie le nom d'utilisateur et le mot de passe fournis par le client, détermine que le client dispose des autorisations appropriées, puis établit la connexion.
2. Cache de requêtes : le serveur MySQL vérifiera le cache de requêtes avant de traiter la requête. Si le jeu de résultats existe déjà dans le cache des requêtes, le serveur renverra directement les résultats dans le cache.
3. Analyseur  : analysez et vérifiez l'exactitude de la syntaxe SQL . L'analyseur divise l'instruction de requête en ses composants, tels que les tables, les colonnes, les conditions, etc. Dans cet exemple, l'analyseur identifie les tables impliquées ( Employee et Employee_score ) et les colonnes requises ( id, name, age, subject, score ).
4.优化器 根据解析器提供的信息生成执行计划。 优化器会分析多种可能的执行策略,并选择成本最低的策略。 在这个示例中,优化器会选择 age 索引和 subject_id score 的联合索引。 对于连接操作,优化器还要决定连接策略,例如是否使用 Nested-Loop Join Hash Join 等一些连接策略。 优化器还会根据表的大小、索引、查询条件和统计信息来决定哪张表作为驱动表,以及选择最佳的连接策略。 例如,如果两个表的大小差异很大, Nested-Loop Join 可能是一个好的选择,而对于大小相似的两个表, Hash Join Sort-Merge Join 可能更加高效。
5.执行器 根据优化器生成的执行计划执行查询,向存储引擎发送请求,获取满足条件的数据行。
6.存储引擎(如InnoDB 管理数据存储和检索。 存储引擎首先接收来自执行器的请求,该请求可能是基于优化器的执行计划。
  • 存储引擎首先接收来自执行器的请求。请求可能包括获取满足查询条件的数据行,以及使用哪种扫描方法(如全表扫描或索引扫描)。
  • 假设执行器已经决定使用索引扫描。在这个示例中,存储引擎可能会先对employee表进行索引扫描(使用age索引),然后对employee_score表进行索引扫描(使用subject_id和score的联合索引)。
  • 存储引擎会根据请求查询相应的索引。在employee索引中会找到满足age > 18条件的记录。在employee_score索引中找到满足subject_id = 3 AND score > 80条件的记录。
  • 一旦找到了满足条件的记录,存储引擎需要将这些记录所在的数据页从磁盘加载到内存中。存储引擎首先检查缓冲池(InnoDB Buffer Pool),看这些数据页是否已经存在于内存中。如果已经存在,则无需再次从磁盘加载。如果不存在,存储引擎会将这些数据页从磁盘加载到缓冲池中。
  • 加载到缓冲池中的记录可以被多个查询共享,这有助于提高查询效率。
7.执行器 :处理连接、排序、聚合、过滤等操作。
  • 在内存中执行连接操作,将employee表和employee_score表的数据行连接起来。
  • 对连接后的结果集进行过滤,只保留满足查询条件(age > 18、subject_id = 3、score > 80)的数据行。
  • 将过滤后的数据行作为查询结果返回给客户端。

前面说过,根据存储引擎根据索引条件加载到内存的数据页有多数据,可能有不满足索引条件的数据,如果执行器不再次进行索引条件判断, 则无法判断哪些记录满足索引条件的,虽然在存储引擎判断过了,但是在执行器还是会有索引条件age > 18、subject_id = 3、score > 80的判断。

我们再以 全局视野 来分析 一下
1.确定驱动表 : 首先, MySQL 优化器会选择一个表作为"驱动表"。 通常,返回记录数较少的表会被选为驱动表。 假设 employee_score 表中满足 subject_id = 3 AND score > 80 条件的记录数量较少,那么这张表可能被选为驱动表。 这是优化器的工作,它预估哪个表作为驱动表更为高效,制定执行计划。 虽然驱动表的选择很大程度上是基于预估的返回记录数,但实际选择还会受其他因素影响,例如表之间的连接类型、可用的索引等。
2.使用驱动表的索引进行筛选 : 优化器会首先对驱动表进行筛选。 如果 employee_score 是驱动表,优化器会使用 subject_id score 的联合索引来筛选出 subject_id = 3 AND score > 80 的记录。 这是执行器按照优化器的计划向存储引擎发出请求,获取需要的数据。 存储引擎负责访问索引,并根据索引定位到实际的数据页,从而获取数据行。
3.连接操作 : 执行器会基于上一步从驱动表中筛选出的记录对另一个表(即 employee 表)进行连接。 这时,执行器会使用 employee 表上的索引(如 id 索引)来高效地找到匹配的记录。
4.一步的筛选 : 在连接的过程中,执行器会考虑 employee 表的其他筛选条件,如 age > 18 ,通常连接后才过滤筛选,这也是执行器的工作,执行器在连接过程中或之后,根据优化器制定的计划进一步筛选结果集。 但是这里 employee 表的 age 索引其叶子节点包含 age 和主键 id 信息,在进行连接时,可以直接按照 age 范围扫描该索引,利用其叶子节点中的 id 信息进行高效的 JOIN 操作,因此在连接时就完成筛选,这个过程由 MySQL 优化器自动完成。 从上面可以看到,当存在可以被利用的索引时, MySQL 可以在连接过程中执行这些过滤操作。
5.返回结果 : 这是执行器最后的步骤,返回最终的查询结果。
四、总结
本文采用一张简单的架构图说明了MySQL查询中使用的组件和组件间关系。
解析了一条sql语句从客户端请求mysql服务器到返回给客户端的整个生命周期流程。
列举了单表sql、关联表sql 两种不同SQL在整个生命周期中的执行顺序以及内部组件逻辑关系。
通过如上案例的解析可以让开发者们掌握到单表sql、关联表sql的底层sql知识,为理解慢sql的产生和优化鉴定基础。
-end-

本文分享自微信公众号 - 京东云开发者(JDT_Developers)。
如有侵权,请联系 [email protected] 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

阿里云严重故障,全线产品受影响(已恢复) 俄罗斯操作系统 Aurora OS 5.0 全新 UI 亮相 汤不热 (Tumblr) 凉了 多家互联网公司急招鸿蒙程序员 .NET 8 正式 GA,最新 LTS 版本 UNIX 时间即将进入 17 亿纪元(已进入) 小米官宣 Xiaomi Vela 全面开源,底层内核为 NuttX Linux 上的 .NET 8 独立体积减少 50% FFmpeg 6.1 "Heaviside" 发布 微软推出全新“Windows App”
{{o.name}}
{{m.name}}

Je suppose que tu aimes

Origine my.oschina.net/u/4090830/blog/10143833
conseillé
Classement