[Optimización lenta del rendimiento de SQL] El ciclo de vida de un SQL


1. El proceso de ejecución de un SQL simple en MySQL.

Un diagrama simple ilustra los componentes de la arquitectura MySQL y la relación entre ellos. A continuación, usaré declaraciones SQL para analizarlo.

Por ejemplo, la siguiente declaración SQL

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

El nombre es el índice, analicémoslo en orden cronológico.

1. Cliente : como la herramienta de línea de comandos MySQL, Navicat, DBeaver u otras aplicaciones para enviar consultas SQL al servidor MySQL.

2. Conector : Responsable de establecer conexiones con clientes, gestionar conexiones y mantener conexiones. Cuando un cliente se conecta a un servidor MySQL , el conector verifica el nombre de usuario y la contraseña del cliente y luego asigna un hilo para manejar la solicitud del cliente.

3. Caché de consultas : el caché de consultas se utiliza para almacenar en caché las consultas ejecutadas previamente y sus resultados. Cuando se recibe una nueva solicitud de consulta, MySQL primero verifica si la misma consulta y sus resultados ya existen en el caché de consultas. Si hay resultados de consulta coincidentes en el caché de consultas, MySQL devolverá directamente los resultados almacenados en caché sin volver a ejecutar la consulta. Sin embargo, si no hay resultados de consulta coincidentes en el caché de consultas, MySQL continuará ejecutando la consulta.
4. Analizador :
  • Analice la declaración de consulta y verifique la sintaxis.
  • Verifique que los nombres de las tablas y columnas sean correctos.
  • Generar árbol de consultas.
5. Optimizador : analice el árbol de consultas, considere varios planes de ejecución, estime los costos de diferentes planes de ejecución y seleccione el mejor plan de ejecución. En este ejemplo, el optimizador puede optar por utilizar el índice de nombre para la consulta porque nombre es la columna de índice.
6. Ejecutor : Según el plan de ejecución seleccionado por el optimizador, envía una solicitud al motor de almacenamiento para obtener filas de datos que cumplan con las condiciones.
7. Motor de almacenamiento (como InnoDB ) :
  • Responsable de ejecutar realmente escaneos de índice, como realizar consultas equivalentes en el índice de nombres de la tabla de empleados. Consultar todas las columnas implica regresar a la tabla y acceder al disco.
  • Antes de acceder al disco, primero verifique si la página de datos requerida ya existe en el grupo de búfer de InnoDB (Buffer Pool). Si hay páginas de datos calificadas en el grupo de búfer, los datos almacenados en caché se utilizan directamente. Si la página de datos requerida no está en el grupo de búfer, cargue la página de datos desde el disco en el grupo de búfer.
8.Actuador :
  • Para cada registro encontrado, determine nuevamente si el registro satisface el nombre de la condición del índice. Esto se debe a que la página de datos cargada en la memoria según la condición de índice también puede contener registros que no cumplen con la condición de índice, por lo que la condición de nombre debe juzgarse nuevamente. Si se cumple la condición de nombre, se aplicará la condición de filtro de edad> 18 seguir siendo juzgado.
  • Registros de grupo que cumplen la condición según depart_id.
  • El ejecutor devuelve el conjunto de resultados procesado al cliente.
Durante la ejecución de la consulta, estos componentes trabajan juntos para ejecutar la consulta de manera eficiente. El cliente es responsable de enviar la consulta, el conector administra la conexión del cliente, el caché de consultas intenta reutilizar los resultados de la consulta anterior, el analizador es responsable de analizar la consulta, el optimizador selecciona el mejor plan de ejecución, el ejecutor ejecuta el plan seleccionado por el optimizador, el motor de almacenamiento (como InnoDB) Responsable de gestionar el almacenamiento y el acceso a los datos. La sinergia de estos componentes permite a MySQL ejecutar consultas de manera eficiente y devolver conjuntos de resultados.
La operación de cargar páginas de datos de índice en la memoria de acuerdo con las condiciones del filtro de la columna de índice la realiza el motor de almacenamiento. Después de cargar en la memoria, el ejecutor juzgará las condiciones de filtro de las columnas indexadas y las columnas no indexadas.

2. Consultar el orden de ejecución de las palabras clave SQL.

La secuencia de ejecución es la siguiente:
1. Operación del motor de almacenamiento.
(1) DE: Tabla de datos utilizada para consultar SQL. El ejecutor obtendrá los datos de las tablas relevantes del motor de almacenamiento de acuerdo con el plan de ejecución seleccionado por el optimizador.
(2) ON: Se utiliza con JOIN para especificar las condiciones de conexión. El ejecutor obtendrá registros que coincidan con las condiciones del motor de almacenamiento de acuerdo con las condiciones dadas por ON. Si la condición de unión implica una columna indexada, el motor de almacenamiento utilizará el índice para la optimización.
(3) UNIRSE: especifique el método de conexión entre tablas (como INNER JOIN, LEFT JOIN, etc.). El ejecutor obtendrá los datos de la tabla de conexiones del motor de almacenamiento de acuerdo con el plan de ejecución seleccionado por el optimizador. Luego, el ejecutor procesa la conexión de datos según el tipo de conexión JOIN y las condiciones de conexión ON.
(4) WHERE: el ejecutor filtra los datos devueltos por el motor de almacenamiento y solo retiene los registros que cumplen con las condiciones de la cláusula WHERE. Si la condición del filtro tiene un índice, la capa del motor de almacenamiento la filtrará a través del índice y lo devolverá.
2. Operaciones con conjuntos de resultados devueltos
(5) GROUP BY: El ejecutor agrupa los registros que cumplen con la condición WHERE de acuerdo con las columnas especificadas por GROUP BY.
(6) TENER: Después de ejecutar la agrupación, el ejecutor filtra nuevamente los registros agrupados según la condición TENER.
(7) SELECCIONAR: el ejecutor obtiene los resultados de la consulta según el plan de ejecución y las columnas especificadas seleccionadas por el optimizador.
(8) DISTINTO: el ejecutor deduplica los resultados de la consulta y solo devuelve registros únicos.
(9) ORDER BY: el ejecutor ordena los resultados de la consulta de acuerdo con las columnas especificadas en la cláusula ORDER BY.
(10) LÍMITE: el ejecutor trunca los resultados de la consulta de acuerdo con las restricciones especificadas en la cláusula LIMIT y solo devuelve parte de los registros.
3. El proceso de ejecución de la consulta de asociación de tablas SQL en 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;
En este ejemplo, sujeto_id y puntuación son índices conjuntos y la edad es el índice. Analicémoslo en orden cronológico .
1. Conector : cuando un cliente se conecta al servidor MySQL , el conector es responsable de establecer y administrar la conexión. Verifica el nombre de usuario y la contraseña proporcionados por el cliente, determina que el cliente tiene los permisos adecuados y luego establece la conexión.
2. Caché de consultas : el servidor MySQL verificará el caché de consultas antes de procesar la consulta. Si el conjunto de resultados ya existe en la caché de consultas, el servidor devolverá directamente los resultados en la caché.
3. Analizador : analiza y verifica la corrección de la sintaxis SQL . El analizador divide la declaración de la consulta en sus partes componentes, como tablas, columnas, condiciones, etc. En este ejemplo, el analizador identifica las tablas involucradas ( empleado y puntuación_empleado ) y las columnas requeridas ( id, nombre, edad, materia, puntuación ).
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}}

Supongo que te gusta

Origin my.oschina.net/u/4090830/blog/10143833
Recomendado
Clasificación