Dos, [mysql] Explica la explicación y el combate real.

El contenido de este capítulo se explica en base a la versión 5.7 de MySQL.

1. Entender Explicar

1.Explicar la introducción

La declaración EXPLAIN proporciona información sobre cómo MySQL ejecuta la declaración. EXPLAIN se aplica a las declaraciones SELECT, DELETE, INSERT, REPLACE y UPDATE.

Utilice la palabra clave EXPLAIN para simular la ejecución de declaraciones SQL por parte del optimizador, analice los cuellos de botella de rendimiento de sus declaraciones o estructuras de consulta y agregue la palabra clave explicar antes de la declaración de selección. MySQL establecerá una marca en la consulta y la ejecución de la consulta devolverá la ejecución. información del plan En lugar de ejecutar este SQL.
Nota: Si from contiene una subconsulta, la subconsulta aún se ejecutará y los resultados se colocarán en una tabla temporal.

Documentación oficial


2. Explicar los campos relacionados.

Primero, se crearon tres tablas, de la siguiente manera:
lista de reparto

 CREATE TABLE `actor` (
 `id` INT(11) NOT NULL,
 `name` VARCHAR(45) DEFAULT NULL,
 `update_time` DATETIME DEFAULT NULL,
 PRIMARY KEY (`id`)
 ) ENGINE=INNODB DEFAULT CHARSET=utf8;

Simplemente inserte usted mismo algunos datos en estas tablas.
Insertar descripción de la imagen aquí

Tabla de películas (se agregó un índice de valor único)

CREATE TABLE `film` (
 `id` INT(11) NOT NULL AUTO_INCREMENT,
 `name` VARCHAR(10) DEFAULT NULL,
 PRIMARY KEY (`id`),
 KEY `idx_name` (`name`)
 ) ENGINE=INNODB DEFAULT CHARSET=utf8;

Tabla de asociación de películas de actores (se agregó un índice conjunto)

CREATE TABLE `film_actor` (
  `id` INT(11) NOT NULL,
  `film_id` INT(11) NOT NULL COMMENT '电影表主键',
  `actor_id` INT(11) NOT NULL COMMENT '演员表主键',
  `remark` VARCHAR(255) DEFAULT NULL COMMENT '额外增加的字段',
  PRIMARY KEY (`id`),
  KEY `idx_film_actor_id` (`film_id`,`actor_id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8

1.particiones

La versión 5.7 tiene esta columna de forma predeterminada al ejecutar explicar, pero es posible que las versiones anteriores no la tengan. Es necesario agregar una palabra clave PARTITIONS.
Es si nuestra tabla tiene particiones, en la mayoría de los casos no se usa, si se usa se dividirá en bases de datos y tablas sin particiones. Si no hay partición, es NULL. Este campo se puede ignorar.

旧版本:EXPLAIN PARTITIONS SELECT * FROM `actor` WHERE id = 1;

5.7之后版本:EXPLAIN  SELECT * FROM `actor` WHERE id = 1;

Insertar descripción de la imagen aquí

2.filtrado

La versión 5.7 tiene esta columna de forma predeterminada al ejecutar explicar, pero es posible que las versiones anteriores no la tengan. Es necesario agregar una palabra clave EXTENDED.

旧版本:EXPLAIN EXTENDED SELECT * FROM `actor` WHERE id = 1;

5.7之后版本:EXPLAIN  SELECT * FROM `actor` WHERE id = 1;

La columna filtrada es un valor de proporción media. Las filas *filtradas/100 pueden estimar el número de filas que se conectarán a la tabla anterior en la explicación (la tabla anterior se refiere a la tabla cuyo valor de identificación en la explicación es menor que el valor de identificación de la tabla actual).

3.COMANDO MOSTRAR ADVERTENCIAS

EXPLAIN   SELECT * FROM `actor` WHERE id = 1;
SHOW WARNINGS;

Insertar descripción de la imagen aquí
MOSTRAR ADVERTENCIAS resultados de ejecución.
Insertar descripción de la imagen aquí

select '1' AS `id`,'Li' AS `name`,'2023-09-04 19:02:55' AS `update_time` from `org_47`.`actor` where 1

El resultado 2 es el resultado de la optimización de mysql de la declaración SQL. Es posible que este resultado no se ejecute directamente.

3. Explicar los campos más importantes

1.id

El número de la columna id es el número de serie de la selección. Hay varias identificaciones ya que hay varias selecciones, y el orden de las identificaciones aumenta en el orden en que aparece la selección.
Cuanto mayor sea la columna de identificación, mayor será la prioridad de ejecución. Si la identificación es la misma, se ejecutará de arriba a abajo. Si la identificación es NULL, se ejecutará en último lugar.

2.seleccionar_tipo

Indica si la fila correspondiente es una consulta simple o compleja.

  1. simple: consulta simple. La consulta no contiene subconsultas ni uniones.
  2. primario: la selección más externa en consultas complejas
  3. subconsulta: subconsulta incluida en select (no en la cláusula from)
  4. derivado: una subconsulta contenida en la cláusula from. MySQL almacenará los resultados en una tabla temporal, también conocida como tabla derivada (el significado en inglés de derivada)

=》ejemplo de sql=》

consulta sencilla

EXPLAIN SELECT * FROM actor WHERE id = 1

Insertar descripción de la imagen aquí
Para consultas que contienen DERIVED,
debe desactivar la nueva función de mysql5.7 para optimizar la combinación de tablas derivadas.
Antes de cerrar

EXPLAIN SELECT (SELECT 1 FROM actor WHERE id = 1) FROM (SELECT * FROM film WHERE id = 1) der

Insertar descripción de la imagen aquí
Desactive la nueva función de mysql5.7 para optimizar la combinación de tablas derivadas

SET SESSION optimizer_switch='derived_merge=off';
EXPLAIN SELECT (SELECT 1 FROM actor WHERE id = 1) FROM (SELECT * FROM film WHERE id = 1) der

Insertar descripción de la imagen aquí
Cuanto mayor sea el id, primero se ejecutará. Si los valores de id son iguales, se ejecutará en orden de filas.
De este ejemplo combinado con 3.table, se puede ver que mysql primero consulta los datos en la tabla de películas, luego consulta la tabla de actores y finalmente consulta la tabla derivada (tabla temporal).

3.mesa

Esta columna indica a qué tabla accede una fila de explicación.
Cuando hay una subconsulta en la cláusula from, la columna de la tabla es el formato, lo que indica que la consulta actual depende de la consulta con id = N, por lo que la consulta con id = N se ejecuta primero
. Cuando hay una unión, el valor de la columna de la tabla de UNION RESULT es <union1,2>, 1 y 2 representan los identificadores de fila seleccionados que participan en la unión.
Por ejemplo, en el ejemplo anterior, 3 depende de 3 en la identificación.
Insertar descripción de la imagen aquí

4.tipo

Esta columna representa el tipo de asociación o tipo de acceso, es decir, MySQL determina cómo encontrar filas en la tabla y el rango aproximado de registros de filas de datos.
De mejor a peor son: system > const > eq_ref > ref > range > index > ALL
En general, es necesario asegurarse de que la consulta alcance el nivel de rango, preferiblemente ref.

  • NULL : mysql puede descomponer la declaración de consulta durante la fase de optimización y no es necesario acceder a tablas o índices durante la fase de ejecución. Por ejemplo, se puede seleccionar el valor mínimo en una columna de índice
    buscando solo el índice, sin acceder a la tabla durante la ejecución. (Esta situación es relativamente rara)
    =》ejemplo de sql=》
EXPLAIN SELECT MIN(id) FROM film;

Insertar descripción de la imagen aquí
En este ejemplo, la columna de la tabla es nula, lo que significa que la declaración de consulta se descompone durante la fase de optimización y los resultados se pueden obtener sin acceder a la tabla o índice durante la fase de ejecución.

  • const, system : MySQL puede optimizar ciertas partes de la consulta y convertirla en una constante (consulte los resultados de mostrar advertencias). Cuando
    todas las columnas de la clave principal o clave única se comparan con constantes, la tabla tiene como máximo una fila coincidente y se lee una vez, lo que es más rápido. El sistema es
    un caso especial de constante: cuando solo hay una tupla coincidente en la tabla, es el sistema.
    =》ejemplo de sql=》
EXPLAIN  SELECT * FROM (SELECT * FROM film WHERE id = 1) tmp;
SHOW WARNINGS;

Insertar descripción de la imagen aquí
Insertar descripción de la imagen aquí

/* select#1 */ SELECT '1' AS `id`,'电影1' AS `name` FROM DUAL
  • eq_ref : la conexión utiliza todas las partes de la clave principal o del índice de clave única y solo se devolverá un registro calificado como máximo. Este puede ser
    el mejor tipo de conexión además de constante. Este tipo no aparecerá en una consulta de selección simple
    =》sql example=》
EXPLAIN SELECT * FROM film_actor LEFT JOIN film ON film_actor.film_id = film.id

Insertar descripción de la imagen aquí

Al realizar una consulta relacionada se deben consultar los datos de ambas tablas, por lo que los valores de id son los mismos, primero se ejecuta la primera fila y luego la segunda fila.

  • ref : En comparación con eq_ref, no utiliza un índice único, sino un índice normal (índice secundario) o un prefijo parcial de un índice único. El índice debe compararse con un determinado valor y se pueden encontrar varias filas calificadas. .
    =》ejemplo sql 1=》
EXPLAIN SELECT * FROM film WHERE NAME = 'film1';

Insertar descripción de la imagen aquí
Este sql usa el índice secundario de esta tabla: idx_name
Insertar descripción de la imagen aquí
= "sql example 2 = "
Consulta de tabla asociada, idx_film_actor_id es el índice conjunto de film_id y actor_id, y aquí se usa la parte del prefijo izquierdo film_id de film_actor.

EXPLAIN SELECT film_id FROM film LEFT JOIN film_actor ON film.id = film_actor.film_id

Insertar descripción de la imagen aquí
Insertar descripción de la imagen aquí

  • rango : el escaneo de rango generalmente ocurre en in(), Between,>,<, >= y otras operaciones. Utilice un índice para recuperar un rango determinado de filas.
    =》ejemplo de sql=》
EXPLAIN SELECT * FROM actor WHERE id > 1;

Insertar descripción de la imagen aquí

  • índice : Los resultados se pueden obtener escaneando todo el índice. Generalmente, se escanea un índice secundario. Este escaneo no comienza desde el nodo raíz del árbol de índice para buscar rápidamente, sino que atraviesa y escanea directamente los nodos de hoja del índice secundario. La velocidad sigue siendo la misma. Relativamente lenta, este tipo de consulta generalmente usa un índice de cobertura y el índice secundario es generalmente relativamente pequeño, por lo que este tipo de consulta suele ser más rápido que TODAS.

Hablemos aquí de cubrir índices:
supongamos que tenemos una tabla user_info con tres columnas: id, nombre y sexo. Agregue un índice de valor único: KEY idx_name (name).

CREATE TABLE `user_info` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL COMMENT '姓名',
  `sex` varchar(2) DEFAULT NULL COMMENT '性别',
  PRIMARY KEY (`id`),
  KEY `idx_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

Datos de la tabla:
Insertar descripción de la imagen aquí

Según nuestro primer blog, la estructura de datos del árbol B+ correspondiente al índice de clave principal y al índice secundario se ve así.

Índice de clave primaria:
Insertar descripción de la imagen aquí

Índice secundario:
Insertar descripción de la imagen aquí
declaración sql:

EXPLAIN SELECT id,NAME FROM `user_info`

Insertar descripción de la imagen aquí
Cuando hay un índice en la columna de nombre: solo consultamos el nombre y la identificación. En la estructura de datos del índice secundario, podemos ver que los nodos hoja satisfacen completamente el contenido de nuestra consulta y, en comparación con el índice de clave primaria, los nodos hoja del índice de clave primaria tienen más datos (al consultar datos, es necesario para colocar los nodos hoja consultados Los datos se cargan en la memoria, el índice de clave principal ocupa más espacio y los datos secundarios ocupan menos espacio). Entonces mysql elige consultar en el índice secundario. El índice secundario cubre el contenido de la columna que se va a consultar. La condición se puede cumplir consultando el índice secundario, es decir, cubriendo el índice. Un índice de cobertura no es un índice, sino una forma.

  • TODOS: Es decir, un escaneo completo de la tabla, que escanea todos los nodos hoja de su índice agrupado. Por lo general, esto requiere agregar índices para la optimización.

5.posibles_claves

Esta columna muestra qué índices puede utilizar la consulta para encontrar.
Cuando se explica, puede haber una situación en la que la columnaposible_keys tiene contenido, pero la clave muestra NULL. Esto se debe a que no hay muchos datos en la tabla y MySQL piensa que el índice no es muy útil para esta consulta, por lo que
elige una consulta de tabla completa.
Si la columna es NULL, no hay ningún índice asociado. En este caso, puede consultar la cláusula dónde para ver si puede crear un índice apropiado para mejorar
el rendimiento de la consulta y luego usar explicar para ver el efecto.
Combine los ejemplos anteriores para comprenderlo.

6.clave

Esta columna muestra qué índice utiliza realmente MySQL para optimizar el acceso a la tabla.
Si no se utiliza ningún índice, la columna es NULL.
Si desea forzar a mysql a usar o ignorar el índice en la columnaposible_keys, use forzar índice e ignorar índice en la consulta .
Combine los ejemplos anteriores para comprenderlo.

7.key_len

Esta columna muestra el número de bytes utilizados por MySQL en el índice. Este valor se puede utilizar para calcular qué columnas del índice se utilizan.
=》ejemplo de sql=》

EXPLAIN SELECT * FROM film_actor WHERE film_id = 999;

Insertar descripción de la imagen aquí
A través de la columna clave, sabemos que esta consulta utiliza el índice idx_film_actor_id, que es un índice conjunto (film_id, actor_id) con dos columnas.
Insertar descripción de la imagen aquí
Ambos son de tipo int. Un int ocupa 4 bytes y dos ints ocupan 4 + 4 = 8 bytes.
Sabemos por la columna key_len como 4 que esta consulta solo usa parte del índice, es decir, el índice relacionado con film_id ¿Por qué es film_id en lugar de actor_id? Combinando el principio más a la izquierda del blog anterior, no es difícil saber que la prioridad del índice conjunto se ordena primero por film_id y luego por actor_id. Si desea consultar actor_id en el índice conjunto, debe asegurarse de que film_id esté en orden. , porque es actor_id.se ordenan según film_id. Cuando no conocemos ken_len, también podemos inferirlo mediante el principio más a la izquierda, es más conveniente tener ken_len.

EXPLAIN SELECT * FROM film_actor WHERE film_id = 999 AND actor_id = 666;

Insertar descripción de la imagen aquí
Este ejemplo significa que todos los campos están indexados.

Las reglas de cálculo de key_len son las siguientes:

  1. Cadenas, char(n) y varchar(n). En las versiones 5.0.3 y posteriores, n representa el número de caracteres, no el número de bytes. Si es UTF-8, un número o letra ocupa 1 byte y otro Carácter chino Ocupa 3 bytes
    (1) char (n): si se almacenan los caracteres chinos, la longitud es de 3n bytes
    (2) varchar (n): si se almacenan los caracteres chinos, la longitud es 3n + 2 bytes, y el Se utilizan 2 bytes adicionales para almacenar caracteres. Longitud de la cadena, porque varchar es una cadena de longitud variable
    (3) varchar es una cadena de longitud variable.
  2. Tipo numérico
    (1) tinyint: 1 byte
    (2) smallint: 2 bytes
    (3) int: 4 bytes
    (4) bigint: 8 bytes
  3. Tipo de hora
    (1) fecha: 3 bytes
    (2) marca de tiempo: 4 bytes
    (3) fecha y hora: 8 bytes

Si el campo permite NULL, se requiere 1 byte para registrar si es NULL.
索引最大长度是768字节,当字符串过长时,mysql会做一个类似左前缀索引的处理,将前半部分的字符提取出来做索引。

8.referencia

Esta columna muestra las columnas o constantes utilizadas por la tabla para buscar valores en el índice del registro de la columna clave, las más comunes son: constante (constante), nombre de campo (nombre de la tabla, nombre de la columna).

EXPLAIN SELECT film_id FROM film LEFT JOIN film_actor ON film.id = film_actor.film_id;

Insertar descripción de la imagen aquí

9.filas

估计Esta columna es el número de filas que MySQL leerá y detectará. Tenga en cuenta que este no es el número de filas en el conjunto de resultados.

10.Adicional

Esta columna muestra información adicional. Los valores comúnmente importantes son los siguientes:

  • Usando índice: use índice de cobertura.
EXPLAIN SELECT film_id FROM film_actor WHERE film_id = 1;

Insertar descripción de la imagen aquí

  • Uso de dónde: utilice la instrucción dónde para procesar los resultados y las columnas consultadas no estarán cubiertas por el índice.
EXPLAIN SELECT * FROM actor WHERE NAME = 'qqqq';

Insertar descripción de la imagen aquí

  • Uso de la condición de índice: la columna consultada no está completamente cubierta por el índice y la condición donde es un rango de columnas principales.
EXPLAIN SELECT * FROM film_actor WHERE film_id > 1;

Insertar descripción de la imagen aquí

  • Uso temporal: mysql necesita crear una tabla temporal para procesar consultas. Cuando esto sucede, la optimización generalmente es necesaria, lo primero que debe hacer es utilizar índices para la optimización.
EXPLAIN SELECT DISTINCT NAME FROM actor

Insertar descripción de la imagen aquí
Este problema se puede resolver agregando un índice al nombre cambiado.
En el ejemplo anterior, el nombre en la tabla de películas está indexado.

EXPLAIN SELECT DISTINCT NAME FROM film

Insertar descripción de la imagen aquí

  • Uso de clasificación de archivos: se utilizará clasificación externa en lugar de clasificación por índice. Cuando los datos son pequeños, se ordenarán en la memoria, de lo contrario, se ordenarán en el disco. En este caso, generalmente es necesario considerar el uso de índices para la optimización. (se explicará en detalle más adelante)
EXPLAIN SELECT * FROM actor ORDER BY NAME;

Insertar descripción de la imagen aquí

EXPLAIN SELECT * FROM film ORDER BY NAME;

Insertar descripción de la imagen aquí

  • Seleccionar tablas optimizadas: cuando se utilizan ciertas funciones agregadas (como max, min) para acceder a un campo que tiene un índice.

4. Optimización del índice real (siga los principios)

Crear mesa

CREATE TABLE `employees` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(24) NOT NULL DEFAULT '' COMMENT '姓名',
  `age` int(11) NOT NULL DEFAULT '0' COMMENT '年龄',
  `position` varchar(20) NOT NULL DEFAULT '' COMMENT '职位',
  `hire_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '入职时间',
  PRIMARY KEY (`id`),
  KEY `idx_name_age_position` (`name`,`age`,`position`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COMMENT='员工记录表'
INSERT INTO employees(NAME,age,POSITION,hire_time) VALUES('LiHua',22,'manager',NOW());
INSERT INTO employees(NAME,age,POSITION,hire_time) VALUES('HanLei',23,'dev',NOW());
INSERT INTO employees(NAME,age,POSITION,hire_time) VALUES('Lucy',23,'dev',NOW());

1. Coincidencia de valor total

Los campos de la condición deben coincidir exactamente

=》ejemplo de sql=》

EXPLAIN SELECT * FROM employees WHERE NAME= 'LiLei';

Insertar descripción de la imagen aquí
¿De dónde viene este key_len? El nombre es varchar (24). Mediante la fórmula anterior, se calcula 3n+2: 3*24+2=74

EXPLAIN SELECT * FROM employees WHERE LEFT(NAME,3)= 'LiLei';

Insertar descripción de la imagen aquí
Para aquellos que no conocen la función izquierda, acepta dos parámetros, a saber, Izquierda (cadena, len), cadena es la cadena que desea interceptar y len es el número de caracteres a interceptar comenzando desde la izquierda.

SELECT LEFT('LiLei',3) AS 结果

Insertar descripción de la imagen aquí

2. Regla del prefijo más a la izquierda

Si se indexan varias columnas, se debe seguir la regla del prefijo más a la izquierda. Esto significa que la consulta comienza desde la columna más a la izquierda del índice y no omite columnas en el índice.
El contenido se ha discutido en detalle antes y aquí solo doy ejemplos.

EXPLAIN SELECT * FROM employees WHERE NAME = 'Bill' AND age = 31;

Insertar descripción de la imagen aquí

EXPLAIN SELECT * FROM employees WHERE age = 30 AND POSITION = 'dev';

Insertar descripción de la imagen aquí

EXPLAIN SELECT * FROM employees WHERE POSITION = 'manager';

Insertar descripción de la imagen aquí

3. No realizar ninguna operación (cálculo, función, conversión de tipo (automática o manual)) en la columna de índice hará que el índice falle y pase a un escaneo completo de la tabla.

= "ejemplo de sql = "
agregar índice

ALTER TABLE `employees` ADD INDEX `idx_hire_time` (`hire_time`) USING BTREE ;
EXPLAIN select * from employees where date(hire_time) ='2018‐09‐30';

Insertar descripción de la imagen aquí

La función DATE (fecha) solo extrae el año, mes y día de la fecha.

SELECT DATE('2018-09-30 :00:00:00') AS 日期

Insertar descripción de la imagen aquí
¿Por qué cambiar la consulta a año, mes y día sin utilizar el índice?
Motivo: debido a que los datos almacenados en el árbol de índice se guardan en año, mes, día, hora, minuto y segundo, el año, el mes y el día por sí solos no pueden corresponder y no hay forma de hacerlos coincidir completamente, lo que resulta en la imposibilidad de índice.
Ideas de optimización:

EXPLAIN SELECT * FROM employees WHERE hire_time >='2018-09-30 00:00:00' 
AND hire_time <='2018-09-30 23:59:59'

Insertar descripción de la imagen aquí

Después de la demostración, elimine el índice.

ALTER TABLE `employees` DROP INDEX `idx_hire_time`

4. El motor de almacenamiento no puede utilizar las columnas a la derecha de la condición de rango en el índice.

=》ejemplo de sql=》

EXPLAIN SELECT * FROM employees WHERE NAME= 'LiLei' AND age = 22 AND POSITION ='manager';

Insertar descripción de la imagen aquí
Se puede ver en ken_len que las tres condiciones están indexadas.
=》ejemplo de sql=》

EXPLAIN SELECT * FROM employees WHERE NAME= 'LiLei' AND age > 22 AND POSITION ='manager';

Insertar descripción de la imagen aquí

Se puede ver en key_len que solo se utilizan los campos de nombre y edad en el índice, y el campo de posición no está indexado.
¿Por qué esto es tan?
En primer lugar, cuando se determina el nombre, se ordena la edad en relación con el nombre y se ordena la posición.
Sin embargo, la segunda condición es cuando la edad es mayor, es decir, cuando la edad es incierta, la posición no está necesariamente en orden. Pero la edad debe estar en orden en relación con un determinado nombre. La edad del índice se puede indexar, pero la posición no.
Es decir, en el rango de nombre='LiLei' Y edad > 22, las posiciones no aparecen de forma continua, es decir, no están ordenadas. Tal vez haya contenido para menores de 23 años, pero no para menores de 24 años, y luego esté disponible para menores de 30 años. En este caso, debe escanear los datos en este rango para ver aquellos que coinciden con POSITION ='manager'.

5. Intente utilizar índices de cobertura (consultas que solo acceden al índice (las columnas de índice incluyen columnas de consulta)) y reduzca las declaraciones select *

El índice de cobertura se mencionó anteriormente. ¿Por qué no se recomienda usar select *? Esto se debe a que si desea usar el índice de cobertura, es posible que los nodos de hoja en el índice no guarden todos los datos de las columnas, pero pueden ser el índice de ciertas columnas. así que intente consultar lo más cerca posible del segundo nivel Índice de datos relacionados.
=》ejemplo de sql=》

EXPLAIN SELECT NAME,age FROM employees WHERE NAME= 'LiLei' AND age = 23 AND POSITION ='manager';

Insertar descripción de la imagen aquí

EXPLAIN SELECT * FROM employees WHERE NAME= 'LiLei' AND age = 23 AND POSITION ='manager';

Insertar descripción de la imagen aquí

6. Mysql no puede usar índices cuando no es igual (!= o <>), no está en, no existe, lo que conducirá a un escaneo completo de la tabla.

<menor que,> mayor que, <=,>= estos, el optimizador interno de mysql evaluará si se utiliza el índice en función de múltiples factores, como la tasa de recuperación, el tamaño de la tabla, etc.

EXPLAIN SELECT * FROM employees WHERE NAME != 'LiHua';

Insertar descripción de la imagen aquí
Se puede ver en la columna clave que no hay índice, ¿por qué sigue siendo así?
Debido a que MySQL tiene un conjunto de lógica de cálculo para determinar si se deben usar índices, puede pensar que puede ser más rápido escanear toda la tabla directamente que el índice. Generalmente, si hay menos datos en la tabla, este puede ser el caso.

7. es nulo, no es nulo En general, no se pueden utilizar índices

EXPLAIN SELECT * FROM employees WHERE NAME IS NULL

Insertar descripción de la imagen aquí

8. Al igual que comenzar con un comodín ('$abc...'), la falla del índice mysql se convertirá en una operación de escaneo completo de la tabla

EXPLAIN SELECT * FROM employees WHERE NAME LIKE '%Li'

Insertar descripción de la imagen aquí

EXPLAIN SELECT * FROM employees WHERE NAME LIKE 'Li%'

Insertar descripción de la imagen aquí

Combinado con la estructura del árbol B+, no es difícil ver que el primer signo de porcentaje, es decir, la cadena cuyo sufijo contiene Li, no está necesariamente ordenada en el árbol B+ y no hay forma de indexar.
Pero después de arreglar el signo de porcentaje y el Li frontal, también son los datos que comienzan con Li. Los datos guardados en el árbol B+ deben estar en orden para que puedan indexarse.

Entonces, si necesito utilizar el primer signo de porcentaje, ¿cómo puedo optimizarlo? Luego intente dejarle usar el índice de cobertura.

EXPLAIN SELECT NAME,age,POSITION FROM employees WHERE NAME LIKE '%Li'

Insertar descripción de la imagen aquí
Cambie el tipo de TODOS a índice.

El signo de porcentaje después de me gusta equivale a una consulta constante.

como KK% es equivalente a = constante, %KK y %KK% son equivalentes a rango

9. El índice de la cadena sin comillas simples no es válido.

EXPLAIN SELECT * FROM employees WHERE NAME = '1000';

Insertar descripción de la imagen aquí

EXPLAIN SELECT * FROM employees WHERE NAME = 1000;

Insertar descripción de la imagen aquí

10. Utilice o o con moderación

Al usarlo para realizar consultas, MySQL no necesariamente usa índices. El optimizador interno de MySQL evaluará en general si se usan índices en función de múltiples factores, como la tasa de recuperación y el tamaño de la tabla. Para obtener más detalles, consulte el contenido de optimización de consultas de rango posterior del blog.

EXPLAIN SELECT * FROM employees WHERE NAME = 'LiHua' OR NAME = 'HanLei';

Insertar descripción de la imagen aquí

11. Optimización de consultas de rango

agregar un índice

ALTER TABLE `employees` ADD INDEX `idx_age` (`age`) USING BTREE ;
EXPLAIN SELECT * FROM employees WHERE age >=1 AND age <=2000;

Insertar descripción de la imagen aquí

Motivo para no utilizar el índice: el optimizador interno de MySQL evaluará si se utiliza el índice como un todo en función de múltiples factores, como la tasa de recuperación y el tamaño de la tabla. Por ejemplo, en este ejemplo, es posible que
el optimizador finalmente elija no utilizar el índice porque la consulta de datos única es demasiado grande
Método de optimización: puede dividir un rango grande en varios rangos pequeños.

EXPLAIN SELECT * FROM employees WHERE age >=1 AND age <=1000;

Insertar descripción de la imagen aquí

EXPLAIN SELECT * FROM employees WHERE age >=1001 AND age <=2000;

Insertar descripción de la imagen aquí
¿Por qué no fue el primero, pero sí el segundo?
Mysql en realidad tiene su propio conjunto de lógica de consulta. Le dará una puntuación a cada plan y finalmente lo ejecutará de acuerdo con el plan con la puntuación más alta. En este caso, elegirá un escaneo completo de la tabla o una consulta de índice. El contenido relacionado con la puntuación se mencionará en el siguiente blog, por lo que aquí está la lógica primero.

Finalmente, elimine el índice.

ALTER TABLE `employees` DROP INDEX `idx_age`;

Supongo que te gusta

Origin blog.csdn.net/xiaobai_july/article/details/132653013
Recomendado
Clasificación