【GaussDB (para MySQL)】 Gran optimización de consultas IN

Este artículo se comparte desde la comunidad de la nube de Huawei " [Columna de tecnología MySQL] GaussDB (para MySQL) Big IN Query Optimization ", autor: base de datos GaussDB.

20240508-164135(WeLinkPC).jpg

Introducción a los antecedentes

En un entorno de producción, a menudo nos encontramos con declaraciones SQL comerciales de clientes para filtrar y consultar, y luego realizar un procesamiento de agregación, y la lista de predicados IN contiene miles o incluso decenas de miles de valores constantes. Como se muestra a continuación, el tiempo de ejecución de dichas declaraciones es muy largo.

 

111.PNG

Optimización de MySQL

Cuando MySQL de código abierto procesa la columna IN (const1, const2, ....), si hay un índice en la columna, el optimizador seleccionará Escaneo de rango para escanear; de lo contrario, utilizará el escaneo completo de la tabla. La variable de sistema range_optimizer_max_mem_size controla la memoria máxima que se puede utilizar durante el análisis del proceso de optimización de rango. Si hay muchos elementos de lista en el predicado IN, el contenido de cada IN se tratará como OR, cada uno de los cuales ocupa aproximadamente 230 bytes. Si hay muchos elementos, se utilizará más memoria. Si el uso de la memoria excede la memoria máxima definida, la optimización del rango fallará y el optimizador cambiará la estrategia, como convertir a un escaneo completo de la tabla, lo que provocará que el rendimiento de la consulta disminuya.

Para este problema de optimización, se puede manejar ajustando range_optimizer_max_mem_size. La memoria definida por range_optimizer_max_mem_size está en el nivel de sesión. Cada sesión que ejecute este tipo de declaración ocupará la misma memoria. En escenarios de gran concurrencia, provocará un uso excesivo de la memoria de la instancia y el riesgo de OOM de la instancia.

Para consultas de rango, MySQL define la variable de sistema eq_range_index_dive_limit para controlar si el optimizador realiza un buceo de índice (index div) al procesar consultas de rango equivalente. El buceo con índice utiliza el índice para completar la descripción del número de tuplas, lo que puede obtener información más precisa y optimizar mejor la estrategia de consulta, pero el tiempo de ejecución también es largo. Cuando el número de combinaciones IN excede un cierto número, el buceo de índice no es aplicable. El sistema utiliza valores de información estadística de índice estático para seleccionar índices. Los resultados obtenidos por este método deben ser precisos. Esto puede hacer que MySQL no pueda hacer un buen uso del índice, lo que provocará una regresión del rendimiento.

Gran optimización IN de GaussDB (para MySQL)

 
GaussDB (para MySQL) El método de problema de rendimiento Big IN convierte grandes predicados IN en subconsultas IN. Por tanto, la forma del predicado IN es:
columna EN (const1, const2, ....)
Convierta a la subconsulta IN correspondiente:
columna EN (SELECCIONAR... DE tabla_temporal)
Después de los cambios anteriores, la consulta de la función IN se convierte en una subconsulta IN y la subconsulta es una subconsulta no correlacionada.
 
Para subconsultas IN no correlacionadas, el optimizador MySQL proporciona una estrategia de materialización de semiunión para el procesamiento de optimización. La estrategia de materialización de semiunión es materializar los resultados de la subconsulta en una tabla temporal y luego unirlos con la apariencia. Como se muestra abajo:
 

1.png

 

La concatenación puede realizarse en dos órdenes:

  • Exploración de materialización: indica una exploración completa de la tabla materializada desde la tabla materializada hasta la apariencia.
  • Búsqueda de materialización: indica que desde la apariencia hasta la tabla materializada, puede usar el generador principal para buscar datos en la tabla materializada.

Exploración física y química.

  1. Ejecute la subconsulta, utilice el índice auto_distinct_key y deduplica los resultados al mismo tiempo;
  2. Guarde los resultados del paso anterior en la plantilla de tabla temporal 1;
  3. Obtenga una fila de datos de la tabla temporal y busque la fila que cumpla con las condiciones adicionales en la apariencia;
  4. Repita el paso 3 hasta que se complete el recorrido de la tabla temporal.

Búsqueda materializada

  1. Ejecute la subconsulta primero;
  2. Guarde los resultados obtenidos en el paso anterior en una tabla temporal;
  3. Tome una fila de datos de la apariencia, vaya a la tabla temporal materializada para encontrar filas que cumplan con las condiciones complementarias, use la clave principal de la tabla materializada y escanee una fila a la vez;
  4. Repita 3 hasta que haya visto el look completo.

El optimizador elige diferentes órdenes de concatenación según el tamaño de la apariencia interior. En escenarios reales, la cantidad de datos en las tablas generalmente consultadas es muy grande, decenas de millones o incluso cientos de millones, la cantidad de elementos en la lista IN es mucho menor que la cantidad de tablas, y el optimizador elegirá la Materialización; -Método de escaneo para escaneo Si se usa la clave principal durante el índice de consulta de apariencia, el número total de filas escaneadas después de la optimización es N. Cuando M es mucho mayor que N, la mejora del rendimiento será muy obvia.

Instrucciones

El parámetro rds_in_predicate_conversion_threshold es un interruptor para modificar la función de consulta en la parte inferior del predicado IN. Cuando el número de elementos en la lista de predicados IN de la declaración SQL excede el valor del parámetro, se iniciará la estrategia de optimización. La función se utiliza a través del valor de esta variable. El siguiente es un ejemplo sencillo que ilustra el uso de la optimización:

Estructura de la mesa

crear tabla t1(id int, a int, clave idx1(a));
buscar frases
seleccione * de t1 donde a en (1,2,3,4,5);

Establezca set rds_in_predicate_conversion_threshold = 0 y configure range_optimizer_max_mem_size=1 para desactivar la función de optimización de predicados IN grandes y la estrategia de optimización de escaneo de rango. Verifique el plan de ejecución de la declaración de consulta anterior.

> establecer rds_in_predicate_conversion_threshold = 0; > establecer range_optimizer_max_mem_size=1; > explique seleccionar * de t1 donde a en (1,2,3,4,5);  
El resultado es el siguiente:
+----+-------------+-------+------------+------+-- -------------+------+---------+------+------+----- -----+-------------+ | identificación | seleccionar_tipo | mesa | particiones | tipo | claves_posibles | clave | clave_len | árbitro | filas | filtrado | Adicional | +----+-------------+-------+------------+------+-- -------------+------+---------+------+------+----- -----+-------------+ | 1 | SENCILLO | t3 | NULO | TODOS | clave1 | NULO | NULO | NULO | 3 | 50,00 | Usando donde | +----+-------------+-------+------------+------+-- -------------+------+---------+------+------+----- -----+-------------+ 1 fila en conjunto, 2 advertencias (0,00 seg)  
mostrar advertencias; +---------+------+-------------------------------- -------------------------------------------------- -----------------------------------------+ | Nivel | Código | Mensaje | +---------+------+-------------------------------- -------------------------------------------------- -----------------------------------------+ | Advertencia | 3170 | Se superó la capacidad de memoria de 1 byte para 'range_optimizer_max_mem_size'. No se realizó optimización de rango para esta consulta. | | Nota | 1003 | /* select#1 */ seleccione `test`.`t3`.`id` AS `id`,`test`.`t3`.`a` AS `a` de `test`.`t3` donde (` prueba`.`t3`.`a` en (3,4,5)) | +---------+------+-------------------------------- -------------------------------------------------- -----------------------------------------+ 2 filas en conjunto (0,00 seg)

Se descubrió que se informó una advertencia cuando se ejecutó la declaración anterior. La información de advertencia mostró que debido a que la memoria utilizada durante el proceso de optimización de rango excedió range_optimizer_max_mem_size, la optimización del límite de rango no se usó para la declaración. Como resultado, el tipo de exploración cambia a TODOS y se convierte en una exploración de tabla completa.

Establezca set rds_in_predicate_conversion_threshold = 3 para habilitar la opción de optimización de predicados IN grandes, lo que significa que cuando los elementos de la lista de predicados IN excedan 3, se activará la estrategia de optimización de consultas de cola IN grandes. Ejecute la instrucción EXPLAIN FORMAT=TREE para ver si la optimización surte efecto.

> establecer rds_in_predicate_conversion_threshold = 3; > explicar formato=árbol seleccionar * de t1 donde a en (1,2,3,4,5); +------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------+ | EXPLICAR | +------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------+ | -> Unión interna de bucle anidado (costo=0,70 filas=1) -> Filtro: (t1.a no es nulo) (costo=0,35 filas=1) -> Escaneo de tabla en t1 (costo=0,35 filas=1) -> Búsqueda de índice de una sola fila en <in_predicate_2> usando <auto_distinct_key> (a=t1.a) (costo=0,35 filas=1) | +------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------+ 1 fila en conjunto (0,00 seg)

La tabla <in_predicate_*> (* es un número) en el plan de ejecución es una tabla temporal construida en Big INTool, que almacena todos los datos en la lista de predicados IN.

Restricciones de uso

Las declaraciones de consulta admitidas por la optimización Big IN incluyen la siguiente lista de declaraciones:

  • elegir
  • Insertar...seleccionar
  • reemplazar...seleccionar
  • punto de vista de apoyo
  • STMT preparado

Restricciones y limitaciones

La consulta del rotor Big IN utiliza la solución de optimización de subconsultas proporcionada por mysql para lograr el rendimiento. Por lo tanto, existen las siguientes restricciones de uso; de lo contrario, reducirá el rendimiento.

  • No se admiten escenarios en los que no se puede utilizar la indexación
  • Solo admite constantes IN LIST (incluidas NOW(), ? y otras declaraciones que no involucran consultas de tablas)
  • Los procedimientos/funciones/activadores almacenados no son compatibles
  • No apoyado o ausente

Comparación de pruebas de escenarios típicos

La estructura de la prueba de la tabla es la siguiente:

CREAR TABLA `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 '' , CLAVE PRIMARIA (`id`), CLAVE `k_1` (`k`) ) MOTOR=InnoDB;  
El volumen de datos de la mesa es de 1000w.
> seleccione recuento (*) de sbtest1; +----------+ | contar(*) | +----------+ | 10000000 | +----------+

La declaración de consulta es la siguiente, en la que el campo de condición está indexado y la lista IN contiene 10,000 números constantes.

seleccione recuento (*) de sbtest1 donde k en (2708275,5580784,7626186,8747250,228703,4589267,5938459,6982345,2665948,4830545,4929382,8723757,354179,1903 875,5111120,5471341,7098051,3113388,2584956,6550102 ,2842606,2744112,7077924,4580644,5515358,1787655,6391388,6044316,2658197,5628504,413887,6058866,3321587,1430333,445303,73 73496,9133196,6760595,4735642,4756387,9845147,9362192,7271805,4351748,6625915 ,3813276,4236692,8308973,4407131,9481423,3301846,432577,810938,3830320,6120078,6765157,6456566,6649509,1123840,2906490,99 65014,3725748, ... );

La comparación de rendimiento se muestra en la siguiente figura:

2.png

Se puede ver que después de la optimización en la lista, el rendimiento mejora 36 veces en comparación con el método original.

Haga clic para seguir y conocer las nuevas tecnologías de Huawei Cloud lo antes posible ~

 

Los estudiantes de secundaria crean su propio lenguaje de programación de código abierto como una ceremonia de mayoría de edad: comentarios agudos de los internautas: confiando en la defensa, Apple lanzó el chip M4 RustDesk Los servicios nacionales fueron suspendidos debido al fraude desenfrenado Yunfeng renunció a Alibaba. En el futuro, planea producir un juego independiente en la plataforma Windows Taobao (taobao.com). Reiniciar el trabajo de optimización de la versión web, destino de los programadores, Visual Studio Code 1.89 lanza Java 17, la versión Java LTS más utilizada, Windows 10 tiene un cuota de mercado del 70%, Windows 11 continúa disminuyendo Open Source Daily | Google apoya a Hongmeng para que se haga cargo; Rabbit R1 de código abierto respalda los teléfonos Android; Haier Electric ha cerrado la plataforma abierta;
{{o.nombre}}
{{m.nombre}}

Supongo que te gusta

Origin my.oschina.net/u/4526289/blog/11105468
Recomendado
Clasificación