Este artículo lo lleva a comprender el uso del índice de árbol B+ de MySQL

prefacio

En nuestro artículo anterior detallamos el índice de árbol B+ del motor de almacenamiento InnoDB, debemos saber las siguientes conclusiones:

  • Cada índice corresponde a un árbol B+, el árbol B+ se divide en varias capas, la capa inferior es el nodo hoja y el resto son nodos internos (nodos no hoja). Todos los registros de usuario se almacenan en los nodos de hoja del árbol B+ y todos los registros de entrada de directorio se almacenan en los nodos internos.

  • El motor de almacenamiento InnoDB creará automáticamente un índice agrupado para la clave principal (si no, se agregará automáticamente para nosotros), y los nodos de hoja del índice agrupado contienen registros de usuario completos.

  • Podemos crear un índice secundario para las columnas que nos interesan. Los registros de usuario contenidos en los nodos de hoja del índice secundario están compuestos por columnas de índice + claves primarias, por lo que si queremos encontrar registros de usuario completos a través del índice secundario, debemos necesita volver a la tabla. , es decir, después de encontrar el valor de la clave principal a través del índice secundario, se busca el registro de usuario completo en el índice agrupado.

  • Cada capa de nodos en el árbol B+ se ordena de acuerdo con el orden de los valores de la columna de índice de menor a mayor para formar una lista doblemente enlazada, y los registros en cada página (ya sean registros de usuario o registros de entrada de directorio) se ordenan de acuerdo a los valores de la columna de índice de pequeño a grande Los grandes grupos secuenciales forman una lista enlazada individualmente. Si se trata de un índice conjunto, las páginas y los registros se ordenan primero según la columna que se encuentra delante del índice conjunto, y si los valores de las columnas son iguales, se ordenan según la columna que se encuentra detrás del índice conjunto.

  • La búsqueda de registros a través del índice comienza desde el nodo raíz del árbol B+ y busca hacia abajo capa por capa. Dado que cada página establece el Page Directory (directorio de páginas) según el valor de la columna de índice, la búsqueda en estas páginas es muy rápida.

Si tiene alguna duda sobre las conclusiones anteriores, se recomienda volver atrás y leer primero el contenido anterior. Después de familiarizarse con el principio del árbol B+, este capítulo le mostrará cómo hacer un mejor uso de los índices.

Índice de árbol B+ [a través del tren]

1. El costo de la indexación

Aunque el índice es algo bueno, no se puede construir aleatoriamente. Antes de aprender a usar mejor los índices, comprendamos el costo de usar índices, que se ralentizará en el espacio y el tiempo.

  • costo de espacio

    Esto es obvio. Cada vez que se crea un índice, se debe construir un árbol B+ para él. Cada nodo de cada árbol B+ es una página de datos. Una página ocupará 16 KB de espacio de almacenamiento de forma predeterminada. Un árbol B+ grande El árbol consta de muchas páginas de datos, que es un gran espacio de almacenamiento.

  • costo de tiempo

    Cada vez que agrega, elimina o modifica datos en la tabla, debe modificar cada índice de árbol B+. Y hemos dicho que los nodos en cada nivel del árbol B+ se ordenan según el valor de la columna de índice de menor a mayor para formar una lista doblemente enlazada. Ya sean los registros en los nodos hoja o los registros en los nodos internos (es decir, ya sea un registro de usuario o un registro de entrada de directorio), se forma una lista unidireccional en el orden de los valores de la columna de índice. de pequeño a grande. Las operaciones de adición, eliminación y modificación pueden dañar el orden de los nodos y los registros, por lo que el motor de almacenamiento necesita tiempo adicional para realizar operaciones como el cambio de registros, la división de páginas y el reciclaje de páginas para mantener el orden de los nodos y los registros. Si construimos muchos índices, el árbol B+ correspondiente a cada índice necesita realizar operaciones de mantenimiento relacionadas, ¿no puede esto entorpecer el rendimiento? Por lo tanto, cuantos más índices se construyan en cada tabla, más espacio de almacenamiento se ocupará y peor será el rendimiento al agregar, eliminar y modificar registros. Para construir buenos y pocos índices, primero debemos aprender las condiciones bajo las cuales funcionan estos índices.

2. Condiciones aplicables del árbol B+

En primer lugar, el índice de árbol B+ no es una panacea, no todas las consultas utilizarán el índice que construimos. A continuación, se presentan algunas situaciones en las que podemos usar el índice de árbol B+ para realizar consultas. Primero, creamos una demo7tabla para almacenar información básica:

mysql> drop table if exists demo7;
Query OK, 0 rows affected (0.01 sec)

mysql> create table demo7(
	c1 int not null auto_increment,
	c2 varchar(11) not null,
	c3 varchar(11) not null,
	c4 char(11) not null,
	c5 varchar(11) not null,
	primary key(c1), key idx_c2_c3_c4(c2,c3,c4) 
);
Query OK, 0 rows affected (0.03 sec)

insert into demo7(c2,c3,c4,c5) values('a','a','a','d');
insert into demo7(c2,c3,c4,c5) values('a','ab','a','d');
insert into demo7(c2,c3,c4,c5) values('a','a','ab','d');				
insert into demo7(c2,c3,c4,c5) values('ab','ab','ab','d');
insert into demo7(c2,c3,c4,c5) values('ab','abc','ab','d');
insert into demo7(c2,c3,c4,c5) values('ab','ab','abc','d');			
insert into demo7(c2,c3,c4,c5) values('abc','abc','abc','d');
insert into demo7(c2,c3,c4,c5) values('abc','abcd','abc','d');
insert into demo7(c2,c3,c4,c5) values('abc','abc','abcd','d');		 
insert into demo7(c2,c3,c4,c5) values('abcd','abcd','abcd','d');
insert into demo7(c2,c3,c4,c5) values('abcd','abcde','abcd','d');
insert into demo7(c2,c3,c4,c5) values('abcd','abcd','abcde','d');

Lo que necesitamos saber sobre esta tabla es:

mysql> show index from demo7;
+-------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table | Non_unique | Key_name     | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+-------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| demo7 |          0 | PRIMARY      |            1 | c1          | A         |          12 |     NULL |   NULL |      | BTREE      |         |               | YES     | NULL       |
| demo7 |          1 | idx_c2_c3_c4 |            1 | c2          | A         |           4 |     NULL |   NULL |      | BTREE      |         |               | YES     | NULL       |
| demo7 |          1 | idx_c2_c3_c4 |            2 | c3          | A         |           8 |     NULL |   NULL |      | BTREE      |         |               | YES     | NULL       |
| demo7 |          1 | idx_c2_c3_c4 |            3 | c4          | A         |          12 |     NULL |   NULL |      | BTREE      |         |               | YES     | NULL       |
+-------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
4 rows in set (0.01 sec)
  • La clave principal de la tabla es c1una columna, que almacena un número entero que aumenta automáticamente, por lo que el motor de almacenamiento de InnoDB creará automáticamente un índice agrupado para la columna de identificación.
  • Además, definimos un índice secundario idx_c2_c3_c4, que es un índice conjunto que consta de tres columnas. Por lo tanto, el registro de usuario almacenado en el nodo hoja del árbol B+ correspondiente a este índice solo puede guardar los valores de las tres columnas de c2, y el valor de la identificación de la clave principal, y no guardará el valor de la columna del país c3.c4

A partir de estos dos puntos, podemos ver nuevamente que hay tantos árboles B+ como índices en una tabla, y demo7se construyen idx_c2_c3_c4dos árboles B+ para el índice agrupado y el índice para la tabla. A continuación, dibujamos idx_c2_c3_c4un diagrama esquemático del índice inferior, pero dado que dominamos el principio del índice de árbol B+ de InnoDB, omitimos algunas partes innecesarias, como la información adicional registrada, cuando dibujamos la imagen para hacerla más clara. número de la página, etc. Usamos flechas para reemplazar la información del número de página de un registro de entrada en el nodo interno. En la estructura del registro, solo se reservan los valores de datos reales de las cuatro columnas, , , por lo que el diagrama esquemático es c2así :c3c4c1

inserte la descripción de la imagen aquí

Sabemos que los nodos internos almacenan registros de entrada de directorio y los nodos hoja almacenan registros de usuario (porque no es un índice agrupado, los registros de usuario están incompletos y carecen de valores de columna). Podemos ver en la figura que el índice corresponde a las páginas c5y idx_c2_c3_c4registros en el árbol B+ se ordenan de la siguiente manera:

  • c2Ordenar por valor de columna primero
  • Ordenar por c2el valor de la columna si el valor de la columna es el mismoc3
  • Si c3el valor de la columna también es el mismo, c4ordenar por el valor de la columna

Esta clasificación es muy importante, porque las páginas y los registros están ordenados, podemos ubicar y buscar rápidamente a través del método de dicotomía, vea esta imagen para comprender el contenido a continuación

2.1 Coincidencia de valor total

Si las columnas en nuestros criterios de búsqueda son consistentes con las columnas del índice, esta es una coincidencia de valor completo, de la siguiente manera:

select * from demo7 where c2='a' and c3='a' and c4= 'ab';

Las tres columnas contenidas en el índice que construimos idx_c2_c3_c4se muestran en esta declaración de consulta.Podemos imaginar el proceso:

  • Debido a que las páginas de datos y los registros del árbol B+ se c2ordenan primero de acuerdo con el valor de la columna, la posición del registro del c2valor de la columna se ubica rápidamentea
  • En c2los registros con la misma columna, c3ordene por el valor de la columna, de modo que en el registro con c2el valor de la columna, adefina rápidamente el registro c3con el valor de la columna‘a’
  • Si, lamentablemente, los valores de las columnas c2y c3son los mismos, los registros se c4ordenan de acuerdo con los valores de las columnas, por lo que se pueden utilizar las tres columnas del índice conjunto.

Tal vez todavía tenemos una pregunta, ¿varias condiciones de búsqueda en la cláusula where afectan los resultados de la consulta? Es decir, ¿decimos que swapping c2y estas pocas columnas buscadas tienen un impacto en el proceso c3de c4ejecución? Por ejemplo, escríbelo así:

select * from demo7 where  c4='ab' and c3= 'a' and c2='a' ;

La respuesta es no, MySQL tiene un componente llamado optimizador de consultas, que analizará estas condiciones de búsqueda y decidirá qué condición de búsqueda usar primero y qué condición de búsqueda usar de acuerdo con el orden de las columnas de índice que se pueden usar, como lo haremos. aprender más tarde

2.2 Coincidir con la columna de la izquierda

De hecho, nuestra declaración de búsqueda no necesita incluir todas las columnas en el índice conjunto, sino que solo incluye la izquierda, como la siguiente declaración:

select * from demo7 where  c2='abc' ;

O incluya varias columnas a la izquierda:

select * from demo7 where c2='abcd' and c3='abcde';  

Entonces, ¿por qué la columna de la izquierda debe aparecer en la condición de búsqueda y también puede usar este índice de árbol B+? Por ejemplo, la siguiente declaración no utiliza el índice de árbol B+.

select * from demo7 where  c3='abcde' ;

Sí, de hecho no se usa, porque las páginas de datos y los registros del árbol B+ se c2ordenan primero según el valor de la columna, y la columna se usa para ordenar c2cuando el valor de la columna es el mismo , es decir , en los registros con diferentes valores de columna Pero ahora omitimos la columna y buscamos directamente según el valor de la columna, lo cual es imposible, entonces, ¿ qué pasa si quiero usar solo el valor de la columna para buscar a través del índice del árbol B+? Esto es fácil de manejar, puede crear un índice de árbol B+ en la columna.c3c2c3c2C3c3c3

Pero una cosa a la que se debe prestar especial atención es que si queremos usar tantas columnas como sea posible en el índice conjunto, cada columna en la condición de búsqueda debe ser la columna continua desde el extremo izquierdo en el índice conjunto. Por ejemplo, idx_c2_c3_c4el orden de definición de las columnas en el índice conjunto es c2, c3, , si solo hay sumas y no hay medios c4en nuestras condiciones de búsqueda , de la siguiente manera:c2c4c3

select * from demo7	where c2 = 'abcd' and c4='abcde';

De esta manera, solo c2se puede usar el índice de la columna, c3y c4el índice de y no se puede usar, porque c2los registros con el mismo valor c3se ordenan según el valor del valor primero, y c3los registros con el mismo c4valor se ordenan según el valor.

2.3 Prefijo de columna de coincidencia

Dijimos anteriormente que indexar una determinada columna significa ordenar los registros del árbol B+ correspondientes utilizando el valor de la columna. Por ejemplo, el demo7índice conjunto establecido en la tabla idx_c2_c3_c4ordenará primero los valores de la columna c2, por lo que esta articulación La disposición de la columna de nombre de los registros en el árbol B+ correspondiente al índice es así:

a
a
a
ab
ab
ab
abc
abc 
abc
abcd 
abcd 
abcd

La esencia de la clasificación de cadenas es comparar qué cadena es más grande y cuál es más pequeña.La comparación del tamaño de las cadenas utiliza el conjunto de caracteres y las reglas de comparación de la columna, que ya hemos mencionado antes. Cabe señalar aquí que las reglas generales de comparación son para comparar el tamaño de los caracteres uno por uno, es decir, el proceso de comparar el tamaño de dos cadenas en realidad es así:

  • Primero compare el primer carácter de la cadena, y la cadena con el primer carácter más pequeño es más pequeña.
  • Si el primer carácter de las dos cadenas es el mismo, compare el segundo carácter y la cadena con el segundo carácter más pequeño es más pequeña.
  • Si el segundo carácter de las dos cadenas también es el mismo, compare el tercer carácter, y así sucesivamente.

Entonces, una columna de cadena ordenada en realidad tiene las siguientes características:

  • Primero ordene por el primer carácter de la cadena.
  • Si el primer carácter es el mismo, ordene según el segundo carácter.
  • Si el segundo carácter es el mismo, ordene según el tercer carácter, y así sucesivamente.

Es decir, los primeros n caracteres de estas cadenas, es decir, los prefijos están todos ordenados, por lo que para la columna de índice del tipo cadena, podemos ubicar rápidamente el registro solo haciendo coincidir su prefijo. Por ejemplo,
queremos registros de consulta cuyos nombres comienzan con 'a', puede escribir una declaración de consulta como esta:

select * from demo7 where c2 like 'a%'

Sin embargo, debe tenerse en cuenta que si solo se proporciona el sufijo o una cadena en el medio, como esta:
select * from demo7 where c2 like '%b%'
MySQL no puede ubicar rápidamente la posición del registro porque hay una 'a en el medio de la cadena 'Las cadenas no están ordenadas, por lo que solo se puede escanear toda la tabla.

2.4 Valor del rango de coincidencia

Mirando hacia atrás en el diagrama de árbol B+ de nuestro índice idx_c2_c3_c4, todos los registros están ordenados según el valor de la columna de índice de menor a mayor, por lo que es muy conveniente para nosotros encontrar registros cuyos valores en la columna de índice estén dentro de un cierto rango. Por ejemplo, la siguiente instrucción de consulta:

select * from demo7 where c2 > 'a' and < 'abcd';

Dado que las páginas de datos y los registros en el árbol B+ se ordenan primero por la columna c2, nuestro proceso de consulta anterior es en realidad el siguiente:

  • Encuentre el registro cuyo valor de c2 es a.
  • Encuentra el registro cuyo valor c2 es abcd

Dado que todos los registros están conectados por lista enlazada (se usa una lista enlazada única entre registros y una lista enlazada doble se usa entre páginas de datos), los registros entre ellos se pueden sacar fácilmente y los valores de clave principal de estos registros se pueden encontrado, y luego Vuelva a la tabla en el índice agrupado para encontrar el registro completo. Sin embargo, debe prestar atención cuando utilice una búsqueda de rango conjunto. Si realiza una búsqueda de rango en varias columnas al mismo tiempo, solo puede usar el índice de árbol B+ cuando realiza una búsqueda de rango en la columna más a la izquierda del índice. Por ejemplo:

select * from demo7 where c2 > 'a' and < 'abcd' and c3 > 'a';

La consulta anterior se puede dividir en dos partes:

  • Utilice las condiciones c2 > 'a' y c2 < 'abcd' para variar c2, y el resultado de la búsqueda puede tener varios registros con diferentes valores de c2.
  • Los registros con diferentes valores de c2 continúan siendo filtrados a través de la condición c3 > 'a'.

De esta manera, para el índice conjunto idx_c2_c3_c4, solo se puede usar la parte de la columna c2, pero no la parte de la columna c3, porque solo cuando el valor de c2 es el mismo, se puede usar el valor de la columna c3 para ordenar , y esta consulta pasa c2 Es posible que los registros para la búsqueda de rango no se ordenen de acuerdo con la columna c3, por lo que el índice de árbol B+ no se utilizará cuando se continúe buscando con la columna c3 en la condición de búsqueda.

2.5 Coincide exactamente con una columna y el rango coincide con otra columna

Para el mismo índice conjunto, aunque solo la columna de índice más a la izquierda se puede usar para la búsqueda de rango en varias columnas, si la columna de la izquierda es una búsqueda exacta, la columna de la derecha se puede usar para la búsqueda de rango, por ejemplo:

select * from demo7 where c2='a' and c3 > 'a' and c3 <'ab' and c4>'a'

Las condiciones de esta consulta se pueden dividir en 3 partes:

  • c2 = 'a', realice una búsqueda precisa en la columna c1, por supuesto, puede usar el índice de árbol B+
  • c3 > 'a' y c3 < 'ab', dado que la columna c2 es una búsqueda exacta, los valores de c2 de los resultados obtenidos después de buscar a través de la condición c2 = 'a' son todos iguales, y se ordenarán según el valor de c3. Entonces, en este momento, la búsqueda de rango de la columna c3 puede usar el índice de árbol B+
  • c4 > 'a', el valor de c3 de los registros buscados a través del rango de c3 puede ser diferente, por lo que esta condición ya no puede usar el índice de árbol B+, y solo puede atravesar los registros obtenidos en el paso anterior de consulta

De manera similar, la siguiente consulta también puede usar este índice conjunto idx_c2_c3_c4:

select * from demo7 where c2='a' and c3= 'a' and c4>'a'

2.6 para clasificar

Cuando escribimos declaraciones de consulta, a menudo necesitamos ordenar los registros consultados de acuerdo con ciertas reglas a través del orden por declaración. En circunstancias normales, solo podemos cargar los registros en la memoria y, luego, algunos algoritmos de clasificación, como clasificación rápida, clasificación por fusión, etc., clasifican estos registros en la memoria y, a veces, el conjunto de resultados de la consulta puede ser demasiado grande para Si la clasificación no se puede realizar en la memoria, es posible utilizar temporalmente el espacio en disco para almacenar resultados intermedios y devolver el conjunto de resultados ordenados al cliente después de que se complete la operación de clasificación. En mysql, este método de clasificación en la memoria o en el disco se denomina colectivamente clasificación de archivos (nombre en inglés: filesort). Se parece a un avión frente a un caracol). Pero si la cláusula order by usa nuestra columna de índice, es posible guardar el paso de ordenar en memoria o hardware, como la siguiente declaración de consulta simple:

select * from demo7 order by c2,c3,c4 limit 10;

El conjunto de resultados de esta consulta debe ordenarse primero de acuerdo con el valor de c2, si los valores registrados de c2 son los mismos, debe ordenarse de acuerdo con c3, si los valores de c3 son los mismos, debe ordenarse de acuerdo con c4. Puede mirar hacia atrás en el diagrama esquemático del índice idx_c2_c3_c4 que construimos, porque el índice de árbol b+ en sí está ordenado de acuerdo con las reglas anteriores, por lo que los datos se extraen directamente del índice y luego se realiza la operación de retorno de la tabla para eliminar el columnas no incluidas en el índice Suficiente. sencillo verdad? Sí, los índices son así de impresionantes.

2.6.1 Consideraciones para clasificar utilizando un índice conjunto

Hay un problema con el índice conjunto que necesita atención. El orden de las columnas detrás de la cláusula order by también se debe dar en el orden de las columnas de índice. Si se da el orden de orden por c4, c3 y c2, entonces no se puede usar el índice de árbol B+.La razón por la cual el índice no se puede usar en este orden inverso se ha mencionado en detalle anteriormente, por lo que no entraré en detalles aquí.

De manera similar, ordenar por c2, ordenar por c2, c3 puede usar parte del índice del árbol B+ en la forma de hacer coincidir la columna izquierda del índice. Cuando el valor de la columna izquierda del índice conjunto es constante, también puede usar la última columna para ordenar, por ejemplo:

select * from demo7 where c2 ='a' order by c3,c4 limit 10;

Esta consulta se puede ordenar usando el índice conjunto porque los registros con el mismo valor en la columna c2 se ordenan según c3 y c4, lo cual se ha dicho muchas veces.

2.6.2 Situaciones en las que no se pueden utilizar índices para ordenar

uso mixto de asc y desc

Para el escenario de clasificación usando un índice conjunto, requerimos que el orden de clasificación de cada columna de clasificación sea el mismo, es decir, cada columna se ordena según la regla asc o todas las columnas se ordenan según la regla desc.

Sugerencia:
si las columnas después de la cláusula orde by no se agregan con asc o desc, se ordenan de acuerdo con las reglas de ordenación de asc de forma predeterminada, es decir, se ordenan en orden ascendente.
¿Por qué hay una regla tan extraña? Esto tiene que volver atrás y pensar en la estructura registrada en el índice conjunto idx_c2_c3_c4:

  • Primero ordene en orden ascendente según el valor de la columna registrada c2.
  • Si los valores registrados en la columna c2 son iguales, ordénalos en orden ascendente según los valores de la columna c3.
  • Si los valores registrados en la columna c3 son iguales, ordénalos en orden ascendente según los valores de la columna c4.

Si el orden de clasificación de cada columna de clasificación en la consulta es consistente, por ejemplo, los dos casos siguientes:

  • order by c2, c3 limit 10
    En este caso, solo lea 10 registros desde el extremo izquierdo del índice hacia la derecha.
  • order by c2 desc, c3 desc limit 10
    En este caso, solo lea 10 registros desde el extremo derecho del índice a la izquierda.

Pero si nuestra consulta debe clasificarse primero en orden ascendente según la columna c2 y luego en orden descendente según la columna c3, por ejemplo, una declaración de consulta de este tipo: si se usa la clasificación por índice, el proceso es así :
select * from demo7 order by c2,c3 desc limit 10;

  • Primero determine el valor mínimo de la columna c2 desde el extremo izquierdo del índice, luego busque todos los registros cuya columna c2 sea igual a este valor y luego busque 10 registros a la izquierda desde el registro más a la derecha cuya columna c2 sea igual a este valor
  • Si hay menos de 10 registros en la columna c2 iguales al valor más pequeño, continúe hacia la derecha para encontrar el registro con el segundo valor más pequeño en c2 y repita el proceso anterior hasta encontrar 10 registros
  • El punto es que el índice no se puede usar de manera eficiente, sino que se necesita un algoritmo más complejo para obtener datos del índice, que no es tan rápido como la clasificación directa de archivos. Por lo tanto, se estipula que el orden de clasificación de cada columna de clasificación utilizando el índice conjunto debe ser consistente.

La columna de índice utilizada para no ordenar aparece en la cláusula where

Si hay una columna de índice que no se usa para clasificar en la cláusula where, la clasificación aún no usa el índice, por ejemplo:

select * from demo7 where c5 =	'a' order by c2 limit 10;

Esta consulta solo puede extraer los registros que cumplen la condición de búsqueda c5='a' y luego ordenarlos, y no se puede usar el índice. Tenga en cuenta la diferencia con la siguiente consulta:

select * from demo7 where c2='a' order by c3,c4 limit 10;

Aunque esta consulta también tiene condiciones de búsqueda, c2 = 'a' puede usar el índice idx_c2_c3_c4, y los registros restantes después del filtrado todavía se ordenan de acuerdo con las columnas c3 y c4, por lo que el índice todavía se puede usar para ordenar.

La columna ordenada contiene columnas que no están en el mismo índice

A veces, varias columnas que se usan para ordenar no están en un índice y, en este caso, el índice no se puede usar para ordenar, por ejemplo:

select * from demo7 order by c2,c5 limit 10;

c2 y c5 no pertenecen a las columnas en un índice conjunto, por lo que el índice no se puede usar para ordenar. En cuanto a por qué, puede echar un vistazo al frente

Las columnas de clasificación utilizan expresiones complejas

Si desea utilizar un índice para las operaciones de clasificación, debe asegurarse de que la columna de índice aparezca como una columna separada, no como una forma modificada, por ejemplo:

select * from demo7 order by upper(c2) limit 10;

Las columnas modificadas con la función superior no son columnas independientes, por lo que no se pueden ordenar mediante índices.

para agrupar

A veces agrupamos los registros de la tabla según determinadas columnas para facilitar las estadísticas de alguna información de la tabla. Por ejemplo, la siguiente consulta de grupo:

select c2,c3,c4,count(*) from demo7 group by c2,c3,c4

Esta instrucción de consulta es equivalente a realizar 3 operaciones de agrupación:

  • Primero agrupe los registros según el valor de c2, y todos los registros con el mismo valor de c2 se dividen en un grupo.
  • Agrupe los registros en cada grupo con el mismo valor de c2 de acuerdo con el valor de c3, y coloque los registros con el mismo valor de c3 en un grupo pequeño, para que parezca que un grupo grande se divide en muchos grupos pequeños.
  • Luego, divida los grupos pequeños generados en el paso anterior en grupos más pequeños de acuerdo con el valor de c4, de modo que parezca que los registros se dividen primero en un grupo grande, luego el grupo grande se divide en varios grupos pequeños y luego en varios grupos pequeños. grupos Los grupos se subdividen en más subgrupos.

Luego cuente esos pequeños grupos.Por ejemplo, en nuestra declaración de consulta, contamos el número de registros contenidos en cada pequeño grupo. Si no hay índice, todo el proceso de agrupación debe implementarse en la memoria, y si hay un índice, sucede que el orden de agrupación es consistente con el orden de las columnas de índice en nuestro árbol b+, y nuestro índice de árbol b+ es Está ordenado de acuerdo con la columna de índice, ¿no es así? Así que puede usar directamente el índice de árbol b+ para agrupar.

Es lo mismo que usar el índice de árbol b+ para ordenar. El orden de las columnas de agrupación también debe ser consistente con el orden de las columnas de índice, o solo se puede usar la columna izquierda en la columna de índice para agrupar.

3. El coste de devolución

La discusión anterior se ha limitado principalmente a la forma de devolución de palabras, y es posible que no tenga una comprensión profunda de la misma. Hablemos de ella en detalle a continuación. Todavía use el índice idx_c2_c3_c4 como ejemplo, vea la siguiente consulta
:

select * from demo7 where c2>'a' and c2<'abcde';

Al consultar utilizando el índice idx_c2_c3_c4, se puede dividir en dos pasos:

  • Del árbol b+ correspondiente al índice idx_c2_c3_c4, saque los registros de usuario cuyo valor de c2 esté entre a y abcde.
  • Dado que el registro de usuario del árbol b+ correspondiente al índice idx_c2_c3_c4 solo contiene cuatro campos c2, c3, c4 y c1, y la lista de consultas es *, significa que todos los campos de la tabla deben consultarse, es decir, el campo c5 debe consultarse. también ser incluido. En este momento, es necesario encontrar el registro de usuario completo en el árbol b+ correspondiente al índice agrupado del campo c1 de cada registro obtenido en el paso anterior, que es lo que solemos llamar de nuevo a la tabla, y luego colocar el registro de usuario completo Devuelto al usuario que realiza la consulta.

Dado que los registros en el árbol b+ correspondientes al índice idx_c2_c3_c4 se ordenarán primero según el valor de la columna c2, el almacenamiento de registros con valores entre a y abcde en el disco está conectado y distribuido en una o más páginas de datos Podemos leer rápidamente estos registros conectados desde el disco.Este método de lectura también se puede llamar E/S secuencial. De acuerdo con los valores del campo c1 de los registros obtenidos en el paso 1 es posible que no estén conectados, y los registros en el índice agrupado se organizan de acuerdo con el orden de c1 (es decir, la clave principal), por lo que de acuerdo con estos valores discontinuos de c1 al clúster El acceso a registros de usuario completos en el índice de clúster puede distribuirse en diferentes páginas de datos, por lo que la lectura de registros de usuario completos puede requerir acceso a más páginas de datos.Este método de lectura también puede denominarse E/S aleatoria. En general, la E/S secuencial tiene mucho más rendimiento que la E/S aleatoria, por lo que el paso 1 puede ejecutarse rápidamente, mientras que el paso 2 es más lento. Entonces, esta consulta que usa el índice idx_c2_c3_c4 tiene dos características:

  • Se utilizarán dos índices de árbol b+, un índice secundario y un índice agrupado
  • El acceso al índice secundario usa E/S secuencial y el acceso al índice agrupado usa E/S aleatoria

Cuantos más registros se deban devolver a la tabla, menor será el rendimiento del uso del índice secundario, e incluso algunas consultas preferirían usar el análisis completo de la tabla en lugar del índice secundario. Por ejemplo, la cantidad de registros de usuario cuyo valor c2 está entre a y abcde representa más del 90 % del número total de registros.Si se usa el índice idx_c2_c3_c4, es necesario devolver más del 90 % de los valores c1. a la tabla. ¿No es esto desagradecido? Es mejor escanear directamente el índice agrupado (es decir, un escaneo completo de la tabla).

Entonces, ¿cuándo usar el método de escaneo de tabla completa y cuándo usar el método de índice secundario + tabla de retorno para ejecutar la consulta? Esto es lo que hace el legendario optimizador de consultas. El optimizador de consultas calculará algunos datos estadísticos sobre
los registros y luego usará estos datos estadísticos para calcular la cantidad de registros que deben devolverse a la tabla de acuerdo con la consulta. condiciones Cuantos más registros en la tabla, más inclinado a usar el escaneo completo de la tabla, y viceversa, tiende a usar índice secundario + tabla de retorno. Por supuesto, el análisis realizado por el optimizador no solo es así de simple, sino que es más o menos este proceso. En general, limitar el número de registros obtenidos por la consulta hará que el optimizador se incline más a elegir la forma de índice secundario + volver a la tabla para la consulta, porque cuantos menos registros se devuelvan a la tabla, mayor será la mejora del rendimiento, como lo anterior La consulta se puede reescribir así:

select * from demo7 where c2>'a' and c2<'abcde' limit 10;

La consulta con límite 10 se agrega para que sea más fácil para el optimizador usar el índice secundario + tabla de retorno para consultar

Para consultas con requisitos de ordenación, también son válidas las condiciones mencionadas anteriormente para consultar por exploración de tabla completa o índice secundario + retorno de tabla. Por ejemplo, la siguiente consulta:

select * from demo7 order by c2,c3,c4;

Dado que la lista de consultas es *, si usa el índice secundario para ordenar, debe devolver todos los registros del índice secundario ordenados a la tabla. El costo de esta operación no es tan bueno como atravesar directamente el índice agrupado y luego ordenar los archivos. (clasificación de archivos) Bajo, por lo que el optimizador tenderá a usar un escaneo completo de la tabla para ejecutar la consulta. Si añadimos una declaración de límite, como esta:

select * from demo7 order by c2,c3,c4 limit 10;

De esta manera, hay muy pocos registros que deben devolverse a la tabla, y el optimizador tenderá a usar el índice secundario + volver a la tabla para ejecutar la consulta.

índice de cobertura

Para despedirnos por completo de la pérdida de rendimiento causada por la operación de devolución de tablas, sugerimos que sea mejor incluir solo columnas de índice en la lista de consultas, por ejemplo:

select c2,c3,c4 from demo7 where c2 >'a' and c2 < 'abcde';

Debido a que solo consultamos los valores de las tres columnas del índice c2, c3 y c4, después de obtener los resultados a través del índice idx_c2_c3_c4, no es necesario buscar las columnas restantes del registro en el índice agrupado, es decir , el valor de la columna c5, que ahorra Se elimina la pérdida de rendimiento causada por la operación de la tabla de retorno. Llamamos a este tipo de consulta que solo necesita usar el índice índice de cobertura. La operación de clasificación también prefiere usar el método de índice de cobertura para realizar consultas, como esta consulta:

select c2,c3,c4 from demo7 order by c2,c3,c4;

Aunque no hay una declaración de límite en esta consulta, se usa el índice de cobertura, por lo que el optimizador de consultas usará directamente el índice idx_c2_c3_c4 para ordenar sin regresar a la tabla.

Por supuesto, si la empresa necesita consultar columnas que no sean el índice, sigue siendo importante garantizar las necesidades de la empresa. Sin embargo, desaconsejamos encarecidamente el uso del símbolo * como lista de consulta. Lo mejor es marcar las columnas que necesitamos consultar a su vez.

4. Cómo elegir un índice

Arriba, tomamos el índice idx_c2_c3_c4 como ejemplo para explicar las condiciones aplicables del índice en detalle A continuación, veremos algunos asuntos a los que debemos prestar atención al crear un índice o escribir una declaración de consulta.

4.1 Cree índices solo para las columnas utilizadas para buscar, ordenar o agrupar

Es decir, solo cree índices para las columnas que aparecen en una cláusula where, una las columnas en una declaración de combinación o las columnas que aparecen en una cláusula order by o group by. Las columnas que aparecen en la lista de consultas no necesitan indexarse:

select c3,c5 from demo7 where name= 'abcd';

Las dos columnas como c3 y c5 en la lista de consultas no necesitan indexarse, solo necesitamos crear un índice para la columna c2 que aparece en la cláusula where

4.2 Considere la cardinalidad de la columna

La cardinalidad de una columna se refiere a la cantidad de datos únicos en una columna. Por ejemplo, una columna contiene los valores 2,5,8,2,5,8,2,5,8. Aunque hay 9 registros, la columna La base de es 3. Es decir, en el caso de un determinado número de filas de registros, cuanto mayor sea la cardinalidad de la columna, más dispersos serán los valores en la columna, y cuanto menor sea la cardinalidad de la columna, más concentrados serán los valores. en la columna El índice de cardinalidad de esta columna es muy importante, lo que afecta directamente si podemos usar el índice de manera efectiva. Suponiendo que la cardinalidad de una columna es 1, es decir, todos los valores registrados en la columna son iguales, entonces es inútil construir un índice para la columna, porque todos los valores son iguales y no se puede ordenar, y la búsqueda rápida no se puede realizar, y si una columna con un índice secundario tiene muchos valores duplicados, y es posible que los registros encontrados usando este índice secundario deban devolverse a la tabla, lo que conducirá a una mayor pérdida de rendimiento . Entonces, la conclusión es: es mejor construir índices para aquellas columnas con cardinalidad grande, y el efecto de construir índices para columnas con demasiada cardinalidad puede no ser bueno.

4.3 El tipo de columna de índice debe ser lo más pequeño posible

Cuando definimos la estructura de la tabla, necesitamos especificar explícitamente el tipo de columna, tomando como ejemplo el tipo entero, hay varios tipos como tinyint, mediumint, int y bigint, el espacio de almacenamiento que ocupan aumenta a su vez. El tamaño de tipo al que nos referimos aquí es el tamaño del rango de datos representado por este tipo. El rango de enteros que se pueden representar, por supuesto, también aumenta secuencialmente. Si queremos indexar una columna de enteros, intente hacer que la columna de índice use un tipo más pequeño si el rango de enteros de la representación lo permite. Por ejemplo, si podemos use int, no usamos bigint, no use int si puede usar mediumint, esto se debe a que:

  • Cuanto más pequeño sea el tipo de datos, más rápida será la operación de comparación durante la consulta (esto es lo que sucede a nivel de la CPU)
  • Cuanto más pequeño es el tipo de datos, menos espacio de almacenamiento ocupa el índice y se pueden colocar más registros en una página de datos, lo que reduce la pérdida de rendimiento causada por la E/S del disco, lo que significa que se pueden almacenar más páginas de datos. memoria para acelerar la eficiencia de lectura y escritura.

Esta sugerencia es más adecuada para la clave principal de la tabla, porque no solo el valor de la clave principal se almacenará en el índice agrupado, sino que también el valor de la clave principal de un registro se almacenará en los nodos de todos los demás índices secundarios. la clave principal es adecuada para tipos de datos más pequeños, lo que significa más ahorro de espacio de almacenamiento y E/S más eficientes.

4.4 Prefijos para valores de cadena indexados

Sabemos que una cadena en realidad se compone de varios caracteres. Si usamos el conjunto de caracteres utf8 para almacenar cadenas en MySQL, se necesitan de 1 a 3 bytes para codificar un carácter. Supongamos que nuestra cadena es muy larga, entonces almacenar una cadena requiere mucho espacio de almacenamiento. Cuando necesitamos crear un índice para esta columna de cadena, significa que hay dos problemas en el árbol B+ correspondiente:

  • Los registros en el índice del árbol B+ necesitan almacenar la cadena completa de la columna, y cuanto más larga sea la cadena, mayor será el espacio de almacenamiento ocupado en el índice.
  • Si las cadenas almacenadas en la columna de índice en el índice del árbol B+ son muy largas, llevará más tiempo comparar las cadenas.

Dijimos anteriormente que los prefijos de cadena de las columnas de índice en realidad están ordenados, por lo que el diseñador de índices propuso un caso para indexar solo los primeros caracteres de la cadena, es decir, en los registros del índice secundario, solo Conservar el primero pocos caracteres de la cadena. De esta manera, aunque la ubicación del registro no se puede ubicar con precisión al buscar registros, se puede ubicar la ubicación del prefijo correspondiente y luego se puede verificar el valor completo de la cadena en la tabla de acuerdo con el valor de la clave principal del registro con el mismo prefijo, y luego comparado. De esta manera, solo la codificación de los primeros caracteres de la cadena se almacena en el árbol B+, lo que no solo ahorra espacio, sino que también reduce el tiempo de comparación de la cadena y probablemente puede resolver el problema de clasificación. si, por ejemplo, estamos construyendo una tabla En la declaración, solo los primeros 10 caracteres de la columna de nombre se indexan de la siguiente manera:

create table demo7(
	c1 int not null auto_increment,
	c2 varchar(11) not null,
	c3 varchar(11) not null,
	c4 char(11) not null,
	c5 varchar(11) not null,
	primary key(c1), key idx_c2_c3_c4(c2(10),c3,c4) 
);  

c2(10) significa que solo se reserva la codificación de los primeros 10 caracteres del registro en el índice de árbol B+ establecido. Esta estrategia de indexar solo el prefijo del valor de la cadena es muy recomendable, especialmente cuando el tipo de cadena se puede almacenar. hay muchos personajes.

Efecto del prefijo de columna de índice en la clasificación

Si se usa el prefijo de la columna de índice, por ejemplo, solo se colocan los primeros 10 caracteres de la columna c2 en el índice secundario, la siguiente consulta puede ser un poco embarazosa:

select * from demo7 order by name limit 10;

Debido a que el índice secundario no contiene información completa de la columna c2, es imposible ordenar los registros con los mismos primeros diez caracteres y diferentes caracteres en el último, es decir, el método de usar el prefijo de columna de índice no admite el uso de clasificación de índice , solo clasificación de archivos .

4.5 Deje que la columna de índice aparezca sola en la expresión de comparación

Supongamos que hay una columna de enteros my_col en la tabla y hemos creado un índice para esta columna. Aunque las dos cláusulas where siguientes tienen la misma semántica, difieren en eficiencia:

  • donde mi_col * 2 < 4
  • donde mi_col < 4/2

La columna my_col en la primera cláusula where no aparece en forma de una columna separada, sino en forma de una expresión como my_col * 2. El motor de almacenamiento recorrerá todos los registros a su vez, y el valor calculado de esta expresión
is It no es inferior a 4, por lo que en este caso no se puede utilizar el índice de árbol b+ creado para la columna my_col. Sin embargo, la columna my_col en la segunda cláusula where no aparece en forma de una columna separada.En este caso, el
índice de árbol b+ se puede usar directamente.

Entonces, la conclusión es: si la columna de índice no aparece como una columna separada en la expresión de comparación, sino como una expresión o llamada de función, el índice no se usa.

4.6 Orden de inserción de clave principal

Sabemos que para una tabla que usa el motor de almacenamiento InnoDB, cuando no creamos explícitamente un índice, los datos de la tabla en realidad se almacenan en los nodos hoja del índice agrupado. Los registros se almacenan en la
página de datos, y las páginas de datos y los registros se clasifican de acuerdo con el orden del valor de la clave principal del registro de menor a mayor, por lo que si los valores de la clave principal de los registros que insertamos aumentan en orden, luego cada vez que insertamos Cuando toda la página de datos esté llena, cambie a la siguiente página de datos y continúe insertando, y si el valor de la clave principal que insertamos es grande o pequeño, será más problemático. Supongamos que los registros almacenados en una página de datos está llena y la clave principal está almacenada en ella. El valor de la clave está entre 1 y 100, e insertamos un registro con un valor de clave principal inferior a 100, necesitamos dividir la página actual en dos páginas y mover algunas registros en esta página a la página recién creada. ¿Qué significa la división de páginas y el cambio de registros? Significa: pérdida de rendimiento! Por lo tanto, si queremos evitar en la medida de lo posible una pérdida de rendimiento tan innecesaria, lo mejor es aumentar el valor de la clave principal del registro insertado, para que no se produzca dicha pérdida de rendimiento. Entonces sugerimos: deje que la clave principal tenga auto_incremento, deje que el motor de almacenamiento genere la clave principal para la tabla en sí, en lugar de insertarla manualmente, por ejemplo, podemos definir la tabla demo7 de esta manera:

create table demo7(
	c1 int not null auto_increment,
	c2 varchar(11) not null,
	c3 varchar(11) not null,
	c4 char(11) not null,
	c5 varchar(11) not null,
	primary key(c1), key idx_c2_c3_c4(c2(10),c3,c4) 
); 

Nuestra identificación de columna de clave principal personalizada tiene el atributo auto_increment, y el motor de almacenamiento completará automáticamente el valor de clave principal incrementado automáticamente para nosotros al insertar registros.

4.7 Índices redundantes y duplicados

A veces, algunos estudiantes, intencionalmente o no, crean múltiples índices en la misma columna, por ejemplo, escriben una declaración de creación de tabla como esta:

create table demo7(
	c1 int not null auto_increment,
	c2 varchar(11) not null,
	c3 varchar(11) not null,
	c4 char(11) not null,
	c5 varchar(11) not null,
	primary key(c1), 
	key idx_c2_c3_c4(c2(10),c3,c4),
	key idx_c2(c2(10))
); 

Sabemos que la columna c2 se puede buscar rápidamente a través del índice idx_c2_c3_c4, y crear un índice específico para la columna c2 se considera un índice redundante. Mantener este índice solo aumentará el costo de mantenimiento y no beneficiará la búsqueda.

En otro caso, podemos crear repetidamente un índice en una columna, por ejemplo así:

create table demo7(
   	c1	int	primary	key,
   	c2	int,
   	unique	uidx_c1	(c1),
   	index	idx_c1	(c1)
); 

Vemos que c1 no es solo la clave principal, sino que también la define como un índice único y define un índice común para ella, pero la clave principal en sí generará un índice agrupado, por lo que el índice único definido y el índice común se repiten. situación a evitar.

Resumir

Los anteriores son solo algunos puntos a los que debemos prestar atención en el proceso de creación y uso del índice de árbol B +. Presentaremos más métodos de optimización y precauciones más adelante, así que permanezca atento. El contenido de este episodio se resume de la siguiente manera:

  • El índice de árbol B+ tiene un costo en espacio y tiempo, así que no cree un índice si no tiene nada que hacer
  • El índice de árbol B+ es adecuado para las siguientes situaciones:
    • coincidencia de valor total
    • coincidir con la columna de la izquierda
    • valor del rango de coincidencia
    • Coincide exactamente con una columna y el rango coincide con otra columna
    • para clasificar
    • para agrupar
  • Al usar índices, debe prestar atención a los siguientes elementos:
    • Indexe solo las columnas utilizadas para buscar, ordenar o agrupar
    • Crear índices para columnas con gran cardinalidad
    • El tipo de columna de índice debe ser lo más pequeño posible.
    • Es posible indexar solo prefijos de valores de cadena
    • Los índices solo se pueden aplicar si la columna de índice aparece sola en la expresión de comparación
    • Para minimizar la aparición de divisiones de página y cambios de registros en el índice agrupado, se recomienda que la clave principal tenga el atributo auto_increment.
    • Ubique y suelte índices duplicados y redundantes en las tablas
    • Intente usar el índice de cobertura para la consulta para evitar la pérdida de rendimiento causada por volver a la tabla.

Hasta ahora, el estudio de hoy ha terminado, espero que te conviertas en un yo indestructible
~~~

No puedes conectar los puntos mirando hacia adelante; solo puedes conectarlos mirando hacia atrás. Así que tienes que confiar en que los puntos se conectarán de alguna manera en tu futuro. Tienes que confiar en algo: tu instinto, destino, vida, karma, lo que sea. Este enfoque nunca me ha defraudado y ha marcado una gran diferencia en mi vida.

Si mi contenido te es útil, por favor 点赞, 评论,, 收藏la creación no es fácil, el apoyo de todos es la motivación para que yo persevere

inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/liang921119/article/details/130647022
Recomendado
Clasificación