Reglas de índice InnoDB en MySQL

Este artículo es un resumen de la columna de "45 conferencias sobre la práctica de MySQL" por Lin Xiaobin.

Índice general

La apariencia del índice es en realidad para mejorar la eficiencia de la consulta de datos, como un catálogo de libros. También hay muchas formas de implementar la indexación. A continuación, se incluye una breve introducción a varios modelos de indexación:

  • La tabla hash, basada en la implementación de la tabla hash, es adecuada para escenarios donde solo hay una consulta equivalente.
  • Los arreglos ordenados tienen un rendimiento excelente en escenarios de consultas de rango y consultas equivalentes, pero el costo de inserción es extremadamente alto y solo es adecuado para motores de almacenamiento estáticos.
  • El árbol de búsqueda binaria se caracteriza por: el valor de todos los nodos en el subárbol izquierdo del nodo principal es menor que el valor del nodo principal, y el valor de todos los nodos en el subárbol derecho es mayor que el valor del nodo principal . La complejidad del tiempo de consulta es O (log (N)) y la complejidad del tiempo de actualización es O (log (N)). Los árboles binarios son los más eficientes para la búsqueda, pero de hecho, la mayor parte del almacenamiento de bases de datos no utiliza árboles binarios. La razón es que el índice no solo se almacena en la memoria, sino que también se escribe en el disco.
  • Árbol de múltiples ramas, cada nodo tiene varios hijos, y se garantiza que el tamaño entre los hijos aumentará de izquierda a derecha. Puede hacer que una consulta lea el disco lo menos posible, es decir, reducir la altura del árbol y la cantidad de IO aleatorias. Tome un índice de campo entero de InnoDB como ejemplo, N = 1200, la altura del árbol es 4, puede almacenar 1200 ^ 3 = 1.7 mil millones. Teniendo en cuenta que el bloque de datos en la raíz del árbol siempre está en la memoria, el índice de un campo entero en una tabla de mil millones de filas requiere solo 3 accesos al disco para encontrar un valor. De hecho, el segundo nivel del árbol tiene una alta probabilidad de estar en la memoria, por lo que la media de accesos al disco es aún menor.

En MySQL, los índices se implementan en la capa del motor de almacenamiento, por lo que no existe un estándar de índice uniforme, es decir, los índices de diferentes motores de almacenamiento funcionan de manera diferente. E incluso si varios motores de almacenamiento admiten el mismo tipo de índice, la implementación subyacente puede ser diferente. Entre ellos, el motor de almacenamiento InnoDB es el más utilizado en bases de datos MySQL.

Modelo de índice de InnoDB

En InnoDB, las tablas se almacenan en forma de índices según el orden de la clave primaria. Las tablas de este método de almacenamiento se denominan tablas organizadas por índices . Y como mencionamos anteriormente, InnoDB usa el modelo de índice de árbol B +, por lo que los datos se almacenan en el árbol B +. Entre ellos, cada índice corresponde a un árbol B + en InnoDB. Además, según el contenido del nodo hoja, el tipo de índice se divide en índice de clave de índice de clave primaria y no primaria.

  • El nodo hoja del índice de clave principal almacena toda la fila de datos. En InnoDB, el índice de clave principal también se denomina índice agrupado (índice agrupado).
  • El contenido del nodo hoja del índice de clave no principal es el valor de la clave principal. En InnoDB, los índices de clave no primaria también se denominan índices secundarios.

Entonces, ¿cuál es la diferencia entre una consulta basada en un índice de clave principal y un índice ordinario?

  • El método de consulta de clave primaria , es decir, la condición de juicio en la cláusula where es el campo de clave primaria, solo se necesita buscar en el árbol B + de ID;
  • El modo de consulta de índice ordinario , es decir, la condición de juicio en la cláusula where es un campo de índice ordinario, por lo que primero debe buscar en el árbol de índice ordinario para obtener el valor de la clave principal y luego volver a buscar en el árbol de índice de clave principal. Este proceso se llama volver a la mesa .

Mantenimiento de índices

Para mantener el orden del índice, el árbol B + debe realizar el mantenimiento necesario al insertar nuevos valores . Es posible que deba mover los datos de forma lógica para dejar espacio para los nuevos. Lo que es peor es que si la página de datos está llena, según el algoritmo del árbol B +, debe solicitar una nueva página de datos y luego mover parte de los datos. Este proceso se llama división de páginas . En este caso, el rendimiento se verá afectado naturalmente. La operación de división de páginas también afecta la utilización de las páginas de datos. Los datos que se colocaron originalmente en una página ahora se dividen en dos páginas, y la utilización general del espacio se reduce en aproximadamente un 50%. Por supuesto, donde hay división, hay fusión. Cuando se reduce la utilización de dos páginas adyacentes debido a la eliminación de datos , las páginas de datos se fusionarán. El proceso de fusión puede considerarse el proceso inverso del proceso de división .

La diferencia entre la clave principal autoincrementada y la clave principal del campo empresarial:

La clave primaria de autoincremento se refiere a la clave principal definida en la columna de autoincremento, que generalmente se define en la declaración de construcción de la tabla: NOT NULL PRIMARY KEY AUTO_INCREMENT. El modo de inserción de datos de la clave primaria autoincrementable está en línea con el escenario de inserción incremental que mencionamos anteriormente. Cada vez que se inserta un nuevo registro, es una operación de adición , no implica mover otros registros y no desencadena la división de los nodos hoja.

A menudo, no es fácil garantizar una inserción ordenada si los campos con lógica empresarial se utilizan como claves primarias, por lo que el costo de escribir datos es relativamente alto. Además, sabemos que cuanto menor es la longitud de la clave principal, menores son los nodos hoja del índice ordinario y menor es el espacio ocupado por el índice ordinario. Por lo tanto, en términos de rendimiento y espacio de almacenamiento, el incremento automático de la clave principal suele ser una opción más razonable.

¿Existe algún escenario adecuado para usar campos comerciales como claves primarias directamente?

Solo hay un índice y es el único índice. Dado que no hay otros índices, no es necesario considerar el tamaño de los nodos hoja de otros índices.

Índice de cobertura

Realice una consulta de selección, si el campo de condición de la cláusula where ya incluye los requisitos del campo de consulta, puede proporcionar directamente los resultados de la consulta sin volver a la tabla, este es el índice de cobertura. Dado que un índice de cobertura puede reducir el número de búsquedas de árboles y mejorar significativamente el rendimiento de la consulta , el uso de un índice de cobertura es un método común de optimización del rendimiento.

Cuando se utiliza un índice de cobertura, generalmente se utiliza un índice conjunto. Aunque el mantenimiento del campo de índice es costoso, el índice de cobertura se utiliza aquí y no es necesario volver a la tabla para verificar toda la fila de registros, lo que reduce el tiempo de ejecución de la declaración.

Principio del prefijo más a la izquierda

En los negocios reales, no es necesario diseñar un índice para cada consulta. Puede combinar el índice conjunto y usar el "prefijo más a la izquierda" del índice para ubicar registros. Los elementos del índice se ordenan según el orden de los campos que aparecen en la definición del índice.

Si desea encontrar todas las personas cuyos nombres son "Zhang" en la primera palabra, la condición de su declaración SQL es "donde el nombre es como 'Zhang%'". En este momento, también puede usar este índice para encontrar el primer registro que cumpla con la condición y luego retroceder hasta que no se cumpla la condición.

Por lo tanto, no solo la definición completa del índice, siempre que se satisfaga el prefijo más a la izquierda, el índice se puede utilizar para acelerar la recuperación. El prefijo más a la izquierda pueden ser los N campos más a la izquierda del índice conjunto , o los M caracteres más a la izquierda del índice de cadena .

Al construir un índice conjunto, ¿cómo organizar el orden de los campos en el índice?

El criterio de evaluación es la reutilización del índice. Debido a que se puede admitir el prefijo más a la izquierda, cuando el índice conjunto (a, b) ya existe, generalmente no es necesario crear un índice en un. Por lo tanto, el primer principio es que si se puede mantener un índice menos ajustando el orden, este orden suele ser una prioridad. Si solo hay declaraciones b en la condición de consulta, el índice conjunto (a, b) no se puede utilizar. En este momento, debe mantener otro índice, lo que significa que debe mantener tanto (a, b) como (b) al mismo tiempo Índices.

Al mismo tiempo, el principio a considerar es el espacio. Por ejemplo, los campos de nombre y edad, el campo de nombre es más grande que el campo de edad, luego le sugiero que cree un índice conjunto de (nombre, edad) y un índice de un solo campo de (edad).

Optimización de empuje hacia abajo de índice

Tome el índice de articulaciones (nombre, edad) como ejemplo. Si hay una demanda ahora: recupere a todos los niños cuyo nombre es Zhang y la edad es de 10 años en la tabla. Entonces, la declaración SQL se escribe así:

mysql> select * from tuser where name like '张%' and age=10 and ismale=1;

Antes de MySQL 5.6, al buscar en el árbol de índices, esta declaración solo podía usar "Zhang" para encontrar el primer registro que cumpliera las condiciones, y luego comenzar a regresar a la tabla uno por uno. Busque la fila de datos en el índice de clave principal y compare los valores del campo.

El pushdown de condición de índice introducido por MySQL 5.6 primero puede hacer juicios sobre los campos contenidos en el índice durante el proceso de recorrido del índice y filtrar directamente los registros que no cumplen con las condiciones y reducir el número de retorno a la tabla. Aquí, InnoDB juzga si la edad es igual a 10 dentro del índice (nombre, edad). Para registros que no son iguales a 10, juzga y salta directamente, y luego regresa a la tabla.

En resumen, mire un ejemplo:

Existe una tabla de este tipo, la definición de la estructura de la tabla es similar a esta:

CREATE TABLE `geek` (
  `a` int(11) NOT NULL,
  `b` int(11) NOT NULL,
  `c` int(11) NOT NULL,
  `d` int(11) NOT NULL,
  PRIMARY KEY (`a`,`b`),
  KEY `c` (`c`),
  KEY `ca` (`c`,`a`),
  KEY `cb` (`c`,`b`)
) ENGINE=InnoDB;

¿Es razonable la estructura de la mesa? ¿Cómo modificar si no es razonable?

(1) El orden de organización del índice agrupado de las claves primarias a, b es equivalente al orden por a, b, es decir, primero ordena por a, luego ordena por b, y c no está ordenado.

(2) La organización del índice ca se ordena primero por c, luego por a, y la clave primaria b se registra al mismo tiempo. De hecho, el efecto es el mismo que el del índice c. Simplemente deje uno de los dos.

(3) La organización del índice cb se ordena primero por c, luego por b, y la clave primaria a se registra al mismo tiempo.

La elección entre índice ordinario e índice único

Podemos echar un vistazo al proceso de ejecución de la declaración de consulta y la declaración de actualización de los dos índices .

Preguntar:

seleccione id de T donde k = 5 k es el campo de índice

El proceso de búsqueda en el árbol índice comienza primero desde la raíz del árbol a través del árbol B +, y busca los nodos hoja por capa, y luego se puede considerar que la página de datos se ubica dentro de la página de datos a través de la dicotomía.

  • Para índices ordinarios, después de encontrar el primer registro que cumple la condición, debe buscar el siguiente registro hasta que se encuentre el primer registro que no cumpla con la condición k = 5.
  • Para un índice único, debido a que el índice define la unicidad, después de encontrar el primer registro que cumple la condición, dejará de buscar.

La brecha de rendimiento causada por esta diferencia es realmente mínima. la razón:

Los datos de InnoDB se leen y escriben en unidades de páginas de datos, en lugar de leer el registro en sí desde el disco, pero en unidades de páginas, se leen en la memoria como un todo. En InnoDB, el tamaño de cada página de datos es de 16 KB por defecto. Cuando se encuentra el registro con k = 5, la página de datos en la que se encuentra está toda en la memoria. Luego, para el índice ordinario, la operación "buscar y juzgar el siguiente registro" que necesita hacerse más requiere solo una búsqueda de puntero y un cálculo. Por supuesto, si el registro k = 5 resulta ser el último registro de la página de datos, entonces, para eliminar el siguiente registro, se debe leer la siguiente página de datos. Esta operación será un poco más complicada. Para los campos enteros, una página de datos puede poner casi mil claves, por lo que la probabilidad de que ocurra esta situación será muy baja. Por lo tanto, cuando calculamos la diferencia de rendimiento promedio, aún podemos considerar que este costo operativo es insignificante para la CPU actual.

Actualizar:

1. Cambiar tampón. Cuando una página de datos necesita ser actualizada, si la página de datos está en la memoria, se actualiza directamente, y si la página de datos no está en la memoria, InnoDB almacenará estas operaciones de actualización en el búfer de cambios sin afectar la consistencia de los datos. De esta manera , no es necesario leer esta página de datos del disco.

Cuando la siguiente consulta necesita acceder a la página de datos, la página de datos se lee en la memoria y luego se ejecutan las operaciones relacionadas con esta página en el búfer de cambios . De esta forma, se puede garantizar la exactitud de la lógica de los datos. Cabe señalar que aunque el nombre se llama cambiar búfer, en realidad son datos los que pueden conservarse. En otras palabras, si el búfer de cambios se copia en la memoria, también se escribirá en el disco .

El búfer de cambio de operación se aplica a la página de datos original , obtener el último resultado del proceso se llama fusión. Además de acceder a esta página de datos para activar una fusión, el sistema tiene subprocesos en segundo plano que se fusionarán periódicamente . Durante el cierre normal de la base de datos, también se realiza la operación de combinación.

El búfer de cambios usa la memoria en el grupo de búferes, por lo que no puede aumentar indefinidamente. El tamaño del búfer de cambios se puede establecer dinámicamente mediante el parámetro innodb_change_buffer_max_size . Cuando este parámetro se establece en 50, significa que el tamaño del búfer de cambios solo puede ocupar hasta el 50% del grupo de búfer.

Obviamente, si la operación de actualización se puede grabar primero en el búfer de cambio para reducir la E / S de lectura aleatoria del disco, la velocidad de ejecución de la instrucción mejorará significativamente. Además, la lectura de datos en la memoria debe ocupar el grupo de búfer, por lo que este método también puede evitar ocupar memoria y mejorar la utilización de la memoria.

2. Para un índice exclusivo, todas las operaciones de actualización deben determinar primero si esta operación viola la restricción de unicidad. Esto debe determinarse leyendo la página de datos en la memoria. Si todo se ha leído en la memoria, será más rápido actualizar la memoria directamente, por lo que la actualización del índice único no puede usar el búfer de cambios.

Cuando la página de destino que se va a actualizar está en la memoria , la diferencia entre el índice ordinario y el índice único sobre el rendimiento de la declaración de actualización es solo un juicio y solo consume una pequeña cantidad de tiempo de CPU.

Cuando la página de destino del registro que se actualizará no está en la memoria , para el índice único, la página de datos debe leerse en la memoria, se juzga que no hay conflicto, se inserta el valor y se ejecuta la declaración termina; para el índice ordinario, el registro se actualizará En el búfer de cambios, finaliza la ejecución de la instrucción.

3. En todos los escenarios de indexación normal, ¿puede el uso del búfer de cambio jugar un papel de aceleración?

Debido a que la fusión es el momento en que los datos se actualizan realmente, y el propósito principal del búfer de cambios es almacenar en caché las acciones de cambio registradas, antes de fusionar una página de datos, más cambios se registran en el búfer de cambios (es decir, el se requieren más cambios en esta página) Cuantas más actualizaciones se realicen), mayor será el beneficio.

Para las empresas que escriben más y leen menos, la probabilidad de que se acceda a la página inmediatamente después de la escritura es relativamente pequeña, y el uso del búfer de cambios es el mejor. Los sistemas de registro y facturación se utilizan comúnmente en este modelo de negocio.

Por el contrario, suponiendo que el modo de actualización de una empresa es consultar inmediatamente después de escribir, incluso si se cumplen las condiciones, la actualización se registrará primero en el búfer de cambios, pero el proceso de fusión se activará inmediatamente porque se accederá a la página de datos. pronto. De esta manera, el número de accesos aleatorios a IO no disminuirá, pero aumentará el costo de mantenimiento del búfer de cambio .

Conclusión :

El índice normal y el índice único son iguales en términos de capacidades de consulta, y la consideración principal es el impacto en el rendimiento de la actualización. Por lo tanto, le sugiero que intente elegir un índice ordinario.

Si todas las actualizaciones son seguidas inmediatamente por consultas para este registro, entonces debe cerrar el búfer de cambios. En otros casos, cambiar el búfer puede mejorar el rendimiento de la actualización.

En el uso real, encontrará que el uso combinado de índices ordinarios y búferes de cambio es muy obvio para actualizar y optimizar tablas con grandes cantidades de datos.

Inspección real:

En primer lugar, la corrección empresarial es la prioridad.

La premisa de nuestro artículo es discutir problemas de rendimiento bajo la condición de que " se ha garantizado que el código comercial no escriba datos duplicados" . Si no se puede garantizar el negocio, o el negocio requiere la base de datos como una restricción, entonces no hay opción y se debe crear un índice único. La importancia de este artículo es que si una gran cantidad de datos se inserta lentamente y la tasa de aciertos de la memoria es baja, puede brindarle una idea adicional para la solución de problemas.

Luego, en algunos escenarios de "biblioteca de archivos", puede considerar el uso de índices normales.

Por ejemplo, los datos en línea solo deben conservarse durante medio año y luego los datos históricos se almacenan en la biblioteca de archivos. En este momento, el archivo de datos es para garantizar que no haya un conflicto de claves únicas. Para mejorar la eficiencia del archivado, puede considerar cambiar el índice único de la tabla a un índice normal.

La diferencia entre cambiar el búfer y rehacer el registro

Queremos ejecutar esta declaración de inserción en la mesa:

mysql> insert into t(id,k) values(id1,k1),(id2,k2);

Aquí, asumimos el estado actual del árbol de índice k. Después de encontrar la posición, la página de datos donde se encuentra k1 está en la memoria (grupo de búfer InnoDB), y la página de datos donde se encuentra k2 no está en la memoria. Como se muestra en la figura es el diagrama de estado de actualización con cambio de búfer.

                                      

Al analizar esta declaración de actualización, encontrará que involucra cuatro partes: memoria, rehacer registro (ib_log_fileX), espacio de tabla de datos (t.ibd), espacio de tabla del sistema (ibdata1).

(1) Página 1 en la memoria, actualice directamente la memoria;

(2) La página 2 no está en la memoria, solo en el área de cambio de búfer de la memoria, registre el mensaje "Quiero insertar una línea en la página 2";

(3) Registre las dos acciones anteriores en el registro de rehacer.

Después de hacer lo anterior, se puede completar la transacción. Por lo tanto, verá que el costo de ejecutar esta instrucción de actualización es muy bajo, es decir, se escriben dos memorias y luego se escribe un disco (las dos operaciones se combinan para escribir un disco), y se escribe secuencialmente. Al mismo tiempo, las dos flechas punteadas en la figura son operaciones en segundo plano y no afectan el tiempo de respuesta de la actualización .

Ahora vamos a ejecutar select * from t donde k en (k1, k2). Aquí, dibujé el diagrama de flujo de estas dos solicitudes de lectura. Si la instrucción de lectura ocurre poco después de la instrucción de actualización y los datos en la memoria todavía están allí, entonces las dos operaciones de lectura en este momento no tienen nada que ver con el espacio de tabla del sistema (ibdata1) y el registro de rehacer (ib_log_fileX).

                                    

(1) Al leer la página 1, regrese directamente de la memoria.

(2) Cuando desee leer la Página 2, debe leer la Página 2 del disco en la memoria y luego aplicar el registro de operaciones en el búfer de cambios para generar una versión correcta y devolver el resultado.

Si simplemente desea comparar los beneficios de estos dos mecanismos para mejorar el rendimiento de la actualización, rehacer el registro principalmente ahorra el consumo de IO de las escrituras de disco aleatorias (convertidas a escritura secuencial) , mientras que el principal ahorro de búfer de cambio es el IO de los discos de lectura aleatoria. Consumo .

Pérdida de búfer de cambio:

Cuando la máquina se apaga y se reinicia, ¿se perderá el búfer de cambio? La pérdida de búfer de cambios no es un asunto trivial, si los datos se leen desde el disco, no hay un proceso de fusión, lo que equivale a la pérdida de datos. ¿Ocurrirá esto?

Aunque solo se actualiza la memoria, cuando se confirma la transacción, también registramos la operación de cambio de búfer en el registro de rehacer, por lo que el búfer de cambio se puede recuperar cuando se recupera el bloqueo.

El flujo de ejecución de la fusión es el siguiente:

 (1) Leer páginas de datos del disco a la memoria (páginas de datos de versiones antiguas);

 (2) Busque los registros del búfer de cambios de esta página de datos (puede haber más de uno) del búfer de cambios, aplíquelos a su vez y obtenga la nueva versión de la página de datos;

 (3) Escribir registro de rehacer, este registro de rehacer contiene cambios de datos y cambios de búfer de cambios.

En este momento, la página de datos y la ubicación del disco correspondiente al búfer de cambio en la memoria no han sido modificadas y son páginas sucias, luego cada una de ellas vacia sus propios datos físicos, que es otro proceso.

El optimizador elige la lógica del índice

El propósito del optimizador para elegir un índice es encontrar un plan de ejecución óptimo y ejecutar la declaración con el menor costo. En la base de datos, la cantidad de filas escaneadas es uno de los factores que afectan el costo de ejecución. Cuantas menos filas se analicen, menos veces se accederá a los datos del disco y se consumirán menos recursos de la CPU. Por supuesto, el número de filas escaneadas no es el único criterio, el optimizador también hará un juicio integral basado en factores tales como si usar tablas temporales y ordenar .

Entonces, la pregunta aquí es: ¿cómo juzgar el número de líneas de escaneo?

Antes de que MySQL comience a ejecutar la declaración, solo puede estimar el número de registros basándose en información estadística. Esta información estadística es la "discriminación" del índice. Cuanto más diferentes valores en un índice, mejor es la discriminación del índice. Y el número de valores diferentes en un índice se llama "cardinalidad". En otras palabras, cuanto mayor sea la base, mejor será la discriminación del índice .

Puede utilizar el método show index from t para ver la cardinalidad de un índice. ¿Cómo obtiene MySQL la cardinalidad del índice?

Aquí hay una breve introducción al método de estadísticas de muestreo de MySQL. Porque toda la tabla se saca para las estadísticas de filas, aunque se pueden obtener resultados precisos, pero el costo es demasiado alto, por lo que solo puede elegir "estadísticas de muestreo".

Al muestrear estadísticas, InnoDB selecciona N páginas de datos por defecto, cuenta los diferentes valores en estas páginas y obtiene un valor promedio, que luego se multiplica por el número de páginas en este índice para obtener la base de este índice. La tabla de datos se actualizará continuamente y las estadísticas del índice no se corregirán. Por lo tanto, cuando el número de filas de datos modificadas supera 1 / M, se activará automáticamente una nueva estadística de índice.

En MySQL, hay dos formas de almacenar estadísticas de índices, que se pueden seleccionar configurando el valor del parámetro innodb_stats_persistent:

  • Cuando está activado, significa que las estadísticas se almacenarán de forma persistente. En este momento, el N predeterminado es 20 y M es 10.
  • Cuando está desactivado, significa que la información estadística solo se almacena en la memoria. En este momento, el N predeterminado es 8 y M es 16.

De hecho, las estadísticas de índice son solo una entrada. Para una declaración específica, el optimizador tiene que juzgar cuántas filas deben escanearse para ejecutar la declaración en sí. Al mismo tiempo, el costo de volver a la tabla debe incluirse en el uso de índices ordinarios.

Dado que la información estadística es incorrecta, corríjala. El comando analizar tabla t se puede utilizar para volver a calcular la información del índice.

¿Cómo resolver la excepción del índice?

  • Una forma es usar el índice de fuerza para seleccionar forzosamente un índice. El principal problema con esto es la puntualidad del cambio, porque la selección de índice incorrecta aún es poco común, por lo que el índice de fuerza generalmente no se escribe primero durante el desarrollo. En cambio, no modificará la instrucción SQL y agregará un índice de fuerza hasta que haya un problema en línea. Pero después de la modificación, es necesario probarlo y lanzarlo, lo que no es lo suficientemente ágil para los sistemas de producción .
  • El segundo método es que podemos considerar modificar la declaración para guiar a MySQL a usar el índice que esperamos. Esta modificación no es un método de optimización general, porque existe cierta coincidencia.
  • El tercer método es que, en algunas escenas raras, podemos crear un índice más apropiado para proporcionar el optimizador para la selección o eliminar el índice mal utilizado.

Indexar el campo de cadena

Supongamos que ahora mantiene un sistema que admite el inicio de sesión en el buzón. La tabla de usuarios se define de la siguiente manera:

mysql> create table SUser(
ID bigint unsigned primary key,
email varchar(64), 
... 
)engine=innodb; 

MySQL admite índices de prefijo , es decir, puede definir parte de la cadena como índice. De forma predeterminada, si crea una declaración de índice sin especificar la longitud del prefijo, el índice contendrá la cadena completa.

对应的创建索引语句:
mysql> alter table SUser add index index1(email);
或
mysql> alter table SUser add index index2(email(6));

Dado que cada campo de buzón en la estructura del índice de correo electrónico (6) solo ocupa los primeros 6 bytes, el espacio ocupado será menor, lo que es la ventaja de utilizar índices de prefijo. Sin embargo, la pérdida que esto trae al mismo tiempo es que puede aumentar la cantidad de escaneos de registros adicionales .

Usando el índice de prefijo, si puede definir la longitud, puede ahorrar espacio sin agregar demasiado costo de consulta adicional.

La pregunta es, ¿hay alguna forma de determinar cuánto tiempo debo usar el prefijo?

Al construir un índice, el enfoque está en la discriminación, y cuanto mayor sea la discriminación, mejor. Porque cuanto mayor es el grado de discriminación, menos valores clave se repiten.

mysql> select 
  count(distinct left(email,4))as L4,
  count(distinct left(email,5))as L5,
  count(distinct left(email,6))as L6,
  count(distinct left(email,7))as L7,
from SUser;

Por supuesto, es probable que el uso del índice de prefijo pierda la discriminación, por lo que debe preestablecer un índice de pérdida aceptable , como el 5%. Luego, en el L4 ~ L7 devuelto, encuentre un valor que no sea menor que L * 95%. Suponiendo que tanto L6 como L7 se satisfacen, puede elegir una longitud de prefijo de 6.

El efecto del índice de prefijo en el índice de cobertura

select id,email from SUser where email='[email protected]';

Por ejemplo, si usa index1 (es decir, la estructura de índice de toda la cadena de correo electrónico) para dicha consulta, puede usar el índice de cobertura para devolver el resultado directamente después de encontrar el resultado de index1, sin tener que volver al Índice de ID para comprobarlo de nuevo. Si usa index2 (es decir, la estructura de índice de correo electrónico (6)), debe volver al índice de ID para determinar el valor del campo de correo electrónico. Incluso si modifica la definición de index2 al índice de prefijo de correo electrónico (18) , en este momento, aunque index2 ya contiene toda la información, InnoDB aún tiene que volver al índice de id y verificar nuevamente, porque el sistema no está seguro si la definición del índice de prefijo está truncada Información completa .

Cuando la distinción de prefijos no es lo suficientemente buena y solo la consulta equivalente se basa en este campo, ¿qué debemos hacer?

  • Método uno, utilice el almacenamiento en orden inverso. Guarde el campo al revés.
  • Método dos, use el campo hash. Cree un campo entero para almacenar el código de verificación del campo y cree un índice en el campo entero. Pero el código de verificación puede entrar en conflicto, por lo que la parte where de la declaración de consulta debe determinar si los valores son exactamente iguales.

Las similitudes y diferencias entre los dos métodos de usar el almacenamiento inverso y usar campos hash:

(1) Ninguno de ellos admite consultas de rango, solo pueden admitir consultas equivalentes.

(2) Desde la perspectiva del espacio extra ocupado, el método de almacenamiento inverso en el índice de la clave principal no consume espacio de almacenamiento adicional y el método de campo hash requiere un campo adicional. Pero si el campo invertido es demasiado largo, el costo casi se compensará con el campo hash adicional.

(3) En términos de consumo de CPU, la función inversa requiere una llamada adicional a la función inversa cada vez que se escribe y lee, mientras que el método de campo hash requiere una llamada adicional a la función crc32 (). Si solo observa la complejidad computacional de estas dos funciones, los recursos de CPU adicionales consumidos por la función inversa serán más pequeños .

(4) En términos de eficiencia de la consulta , el rendimiento de la consulta mediante el método de campo hash es relativamente más estable . Debido a que el valor calculado por crc32 tiene una probabilidad de conflicto, pero la probabilidad es muy pequeña, se puede considerar que el número promedio de filas de exploración por consulta es cercano a 1. Después de todo, el método de almacenamiento inverso todavía utiliza el método de índice de prefijo, lo que significa que aumentará el número de líneas de exploración.

 

 

Supongo que te gusta

Origin blog.csdn.net/qq_24436765/article/details/111138187
Recomendado
Clasificación