¿MySQL no existe realmente no indexa?

En algunos escenarios comerciales, la declaración NOT EXISTS se utiliza para garantizar que los datos devueltos no existan en una colección específica. Algunos colegas encontrarán que el rendimiento de NOT EXISTS es pobre en algunos escenarios, y algunos rumores en línea incluso dicen " NOT EXISTS no toma el índice ", que es la declaración NOT EXISTS , ¿Cómo lo optimizamos?

Tome el SQL optimizado de hoy como ejemplo, el SQL antes de la optimización es:

SELECT count(1)
FROM t_monitor m
WHERE NOT exists (
  SELECT 1
  FROM t_alarm_realtime AS a
  WHERE a.resource_id=m.resource_id
  AND a.resource_type=m.resource_type
  AND a.monitor_name=m.monitor_name
)

Usamos el método LEFT JOIN para optimizar, el SQL optimizado es:

SELECT count(1)
FROM t_monitor m
LEFT JOIN t_alarm_realtime AS a
   ON a.resource_id=m.resource_id
  AND a.resource_type=m.resource_type
  AND a.monitor_name=m.monitor_name
WHERE a.resource_id is NULL

Efecto de optimización:

El tiempo de ejecución fue de más de 29 segundos antes de la optimización, 1,2 segundos después de la optimización y la optimización aumentó 25 veces.

¿NO EXISTE realmente no indexa?

¡Vea el plan de ejecución de los dos SQL!

Plan de ejecución utilizando el método NO EXISTE:

Plan de ejecución utilizando el método LEFT JOIN:

Desde el plan de ejecución, ambas tablas usan índices, la diferencia es que NOT EXISTS usa el método " DEPENDENT SUBQUERY ", mientras que LEFT JOIN usa el método normal de asociación de tablas.

Se recomienda mirar: ¿Por qué el índice puede mejorar la velocidad de consulta?

Vea el proceso de ejecución de los dos métodos a través del método de creación de perfiles proporcionado por MySQL .

Proceso de ejecución utilizando el método NO EXISTE:

El proceso de ejecución de usar el modo LEFT JOIN:

Desde la perspectiva del proceso de ejecución, el método LEFT JOIN consume principalmente datos de envío (1.2s), mientras que el método NOT EXISTS consume principalmente datos de ejecución y envío, lo cual está limitado por el hecho de que la creación de perfiles solo almacena 100 filas de registros.

De la creación de perfiles, solo se pueden ver 47 combinaciones de "ejecutar y enviar datos" (cada combinación es aproximadamente 50us). En el plan de ejecución se puede ver que el volumen de datos de la tabla externa t_monitor es 578,436. Ignorando la información estadística inexacta, El uso del método NO EXISTE debería producir 578436 elementos de combinación de "ejecución y envío de datos", el tiempo de consumo total = 50μs * 578436 = 28921800us = 28,92s.

Se puede inferir del proceso de ejecución anterior:

El rendimiento de ejecución del método NOT EXISTS depende en gran medida del número de ejecuciones de la subconsulta NOT EXISTS, es decir, la cantidad de datos en el conjunto de resultados de la consulta externa.

  1. Cuando la cantidad de datos N del conjunto de resultados de la consulta externa es pequeña, el rendimiento de la ejecución es mejor. Si N = 10, el tiempo de ejecución es 50μs * 10 = 500us = 0.005s, más un consumo adicional, el resultado de la ejecución también puede ser de 0.01 segundos o 10 En milisegundos, este tiempo de respuesta debería ser aceptable para la mayoría de las aplicaciones.

  2. Cuando la cantidad de datos N en el conjunto de resultados externo de Chengxun es grande o incluso decenas de millones de datos, el rendimiento de la consulta de NO EXISTE será muy malo e incluso se consumirá una gran cantidad de recursos de CPU y E / S del servidor, lo que afectará el funcionamiento normal de otras empresas.

Además de los problemas anteriores, se descubrió durante el proceso de optimización que la columna resource_id que debe almacenar los mismos datos se define de manera diferente en las dos tablas, una tabla es VARCHAR y la otra tabla es BIGINT, el tipo de campo del conjunto de resultados externo y el campo en la tabla de palabras NO EXISTE Los diferentes tipos dan como resultado la imposibilidad de utilizar índices en subconsultas NO EXISTE, lo que hace que el rendimiento de la subconsulta sea deficiente y, en última instancia, afecta el rendimiento de ejecución de toda la consulta.

Ha habido muchos casos similares en JD.com. Algunas tablas usan VARCHAR para almacenar el número de orden, mientras que otras tablas usan BIGINT para almacenarlos. El rendimiento de las dos tablas es extremadamente pobre cuando se administran las dos tablas. Espero que los colegas de I + D se den cuenta. Siga la pila de tecnología Java de número público y responda a m36 para obtener una copia de las regulaciones militares de I + D de MySQL.

Declaración de derechos de autor: este artículo es el artículo original del blogger y sigue el acuerdo de derechos de autor CC 4.0 BY-SA. Adjunte el enlace de la fuente original y esta declaración para reimprimir. Enlace a este artículo: https://blog.csdn.net/guanfengliang1988/article/details/92814376

Recomiendo leer más en mi blog:

1. Una serie de tutoriales sobre Java JVM, colecciones, subprocesos múltiples y nuevas funciones.

2. Serie de tutoriales Spring MVC, Spring Boot, Spring Cloud

3. Tutorial de herramientas de la serie Maven, Git, Eclipse, Intellij IDEA

4. Las últimas preguntas de la entrevista de los principales fabricantes, como Java, back-end, arquitectura y Alibaba.

¡Siéntete bien, no te olvides de dar me gusta + reenviar!

Finalmente, preste atención a la cuenta oficial de WeChat del líder de la pila: pila de tecnología Java, responda: Bienestar, puede obtener una copia gratuita de las últimas preguntas de la entrevista de Java que he compilado para 2020. Es realmente completo (incluidas las respuestas), sin ninguna rutina.

Supongo que te gusta

Origin blog.csdn.net/youanyyou/article/details/108440426
Recomendado
Clasificación