sql >> Base de Datos >  >> RDS >> MariaDB

Una guía para los índices de MySQL

Cuando se menciona la optimización de consultas de MySQL, los índices son una de las primeras cosas que se cubren. Hoy intentaremos ver por qué son tan importantes.

¿Qué son los índices?

En general, un índice es una lista alfabética de registros con referencias a las páginas en las que se mencionan. En MySQL, un índice es una estructura de datos utilizada para encontrar filas rápidamente. Los índices también se denominan claves y esas claves son críticas para un buen rendimiento:a medida que los datos crecen, la necesidad de usar los índices correctamente puede volverse cada vez más importante. El uso de índices es una de las formas más poderosas de mejorar el rendimiento de las consultas:si los índices se usan correctamente, el rendimiento de las consultas puede aumentar decenas o incluso cientos de veces.

Hoy, intentaremos explicar los beneficios y las desventajas básicas del uso de índices en MySQL. Tenga en cuenta que los índices de MySQL por sí solos merecen un libro completo, por lo que esta publicación no cubrirá absolutamente todo, pero será un buen punto de partida. Para aquellos que estén interesados ​​en cómo funcionan los índices en un nivel más profundo, la lectura del libro Relational Database Index Design and the Optimizers de Tapio Lahdenmäki y Michael Leach debería brindarles más información.

Los beneficios de usar índices

Hay algunos beneficios principales de usar índices en MySQL y estos son los siguientes:

  • Los índices permiten encontrar rápidamente filas que coincidan con una cláusula WHERE;
  • Los índices pueden ayudar a que las consultas eviten buscar en ciertas filas, lo que reduce la cantidad de datos que el servidor necesita examinar; si se puede elegir entre varios índices, MySQL generalmente usa el índice más selectivo, ese es un índice que encuentra la menor cantidad de filas;
  • Los índices pueden usarse para recuperar filas de otras tablas en operaciones JOIN;
  • Los índices pueden usarse para encontrar el valor mínimo o máximo de una columna específica que usa un índice;
  • Los índices se pueden usar para ordenar o agrupar una tabla si las operaciones se realizan en el prefijo más a la izquierda de un índice; de ​​manera similar, el optimizador de consultas también puede usar un prefijo más a la izquierda de un índice de varias columnas para buscar filas;
  • Los índices también se pueden usar para guardar la E/S del disco:cuando se usa un índice de cobertura, una consulta puede devolver valores directamente desde la estructura del índice para guardar la E/S del disco.

Del mismo modo, existen varios tipos de índices:

  • INDEX es un tipo de índice donde los valores no necesitan ser únicos. Este tipo de índice acepta valores NULL;
  • El ÍNDICE ÚNICO se usa con frecuencia para eliminar filas duplicadas de una tabla; este tipo de índice permite a los desarrolladores imponer la unicidad de los valores de fila;
  • FULLTEXT INDEX es un índice que se aplica en campos que utilizan capacidades de búsqueda de texto completo. Este tipo de índice busca palabras clave en el texto en lugar de comparar directamente los valores con los valores del índice;
  • El ÍNDICE DESCENDENTE es un índice que almacena filas en orden descendente:el optimizador de consultas elegirá este tipo de índice cuando la consulta solicite un orden descendente. Este tipo de índice se introdujo en MySQL 8.0;
  • PRIMARY KEY también es un índice. En pocas palabras, la CLAVE PRINCIPAL es una columna o un conjunto de columnas que identifica cada fila en una tabla, que se usa con frecuencia junto con campos que tienen un atributo AUTO_INCREMENTO. Este tipo de índice no acepta valores NULL y, una vez configurados, los valores de PRIMARY KEY no se pueden cambiar.

Ahora, intentaremos analizar tanto los beneficios como los inconvenientes de usar índices en MySQL. Comenzaremos con la ventaja probablemente discutida con más frecuencia:acelerar las consultas que coinciden con una cláusula WHERE.

Aceleración de consultas que coinciden con una cláusula WHERE

Los índices se utilizan con frecuencia para acelerar las consultas de búsqueda que coinciden con una cláusula WHERE. La razón por la que un índice hace que tales operaciones de búsqueda sean más rápidas es bastante simple:las consultas que usan un índice evitan un escaneo completo de la tabla.

Para acelerar las consultas que coinciden con una cláusula WHERE, puede utilizar la instrucción EXPLAIN en MySQL. La declaración EXPLAIN SELECT debería brindarle una idea de cómo el optimizador de consultas MySQL ejecuta la consulta; también puede mostrarle si la consulta en cuestión usa un índice o no y qué índice usa. Eche un vistazo a la siguiente explicación de la consulta:

mysql> EXPLAIN SELECT * FROM demo_table WHERE field_1 = “Demo” \G;

*************************** 1. row ***************************

<...>

possible_keys: NULL

key: NULL

key_len: NULL

<...>

La consulta anterior no utiliza un índice. Sin embargo, si agregamos un índice en "field_1", el índice se usará con éxito:

mysql> EXPLAIN SELECT * FROM demo_table WHERE field_1 = “Demo” \G;

*************************** 1. row ***************************

<...>

possible_keys: field_1

key: field_1

key_len: 43

<...>

La columna possible_keys describe los posibles índices que MySQL puede elegir, la columna key describe el índice realmente elegido y la columna key_len describe la longitud de la clave elegida.

En este caso, MySQL realizaría una búsqueda de los valores en el índice y devolvería las filas que contuvieran el valor especificado; como resultado, la consulta sería más rápida. Aunque los índices ayudan a que ciertas consultas sean más rápidas, hay un par de cosas que debe tener en cuenta si desea que sus índices ayuden a sus consultas:

  • Aísle sus columnas:MySQL no puede usar índices si las columnas en las que se usan los índices no están aisladas. Por ejemplo, una consulta como esta no usaría un índice:
    SELECT field_1 FROM demo_table WHERE field_1 + 5 = 10;

Para resolver esto, deje la columna que va después de la cláusula WHERE sola; simplifique su consulta tanto como sea posible y aísle las columnas;

  • Evite usar consultas LIKE con un comodín anterior; en este caso, MySQL no usará un índice porque el comodín anterior significa que puede haber cualquier cosa antes del texto. Si debe utilizar consultas LIKE con comodines y desea que las consultas utilicen índices, asegúrese de que el comodín esté al final de la instrucción de búsqueda.

Por supuesto, la aceleración de las consultas que coinciden con una cláusula WHERE también se puede hacer de otras maneras (por ejemplo, particionando), pero en aras de la simplicidad, no profundizaremos en eso en esta publicación.

Sin embargo, lo que nos podría interesar son los diferentes tipos de tipos de índice, por lo que lo analizaremos ahora.

Deshacerse de valores duplicados en una columna:índices ÚNICOS

El propósito de un índice ÚNICO en MySQL es hacer cumplir la unicidad de los valores en una columna. Para usar un índice ÚNICO, ejecute una consulta CREAR ÍNDICE ÚNICO:

CREATE UNIQUE INDEX demo_index ON demo_table(demo_column);

You can also create a unique index when you create a table:

CREATE TABLE demo_table (
`demo_column` VARCHAR(100) NOT NULL,
UNIQUE KEY(demo_column)
);

Eso es todo lo que se necesita para agregar un índice único a una tabla. Ahora, cuando intente agregar un valor duplicado a la tabla, MySQL regresará con el siguiente error:

#1062 - Duplicate entry ‘Demo’ for key ‘demo_column’

Índices de TEXTO COMPLETO

Un índice FULLTEXT es un índice que se aplica a las columnas que usan capacidades de búsqueda de texto completo. Este tipo de índice tiene muchas capacidades únicas, incluidas palabras vacías y modos de búsqueda.

La lista de palabras vacías de InnoDB tiene 36 palabras mientras que la lista de palabras vacías de MyISAM tiene 143. En InnoDB, las palabras vacías se derivan de la tabla configurada en la variable innodb_ft_user_stopword_table, de lo contrario, si esta variable no está configurada, se derivan de la variable innodb_ft_server_stopword_table. Si ninguna de esas dos variables está configurada, InnoDB usa la lista integrada. Para ver la lista predeterminada de palabras vacías de InnoDB, consulte la tabla INNODB_FT_DEFAULT_STOPWORD.

En MyISAM, las palabras vacías se derivan del archivo storage/myisam/ft_static.c. La variable ft_stopword_file permite cambiar la lista de palabras vacías predeterminada. Las palabras vacías se desactivarán si esta variable se establece en una cadena vacía, pero tenga en cuenta que si esta variable define un archivo, el archivo definido no se analiza en busca de comentarios:MyISAM tratará todas las palabras encontradas en el archivo como palabras vacías.

Los índices FULLTEXT también son famosos por sus modos de búsqueda únicos:

  • Si se ejecuta una consulta de búsqueda de TEXTO COMPLETO sin modificadores, se activará un modo de lenguaje natural. El modo de lenguaje natural también se puede activar usando el modificador EN MODO DE LENGUAJE NATURAL;
  • El modificador CON EXPANSIÓN DE CONSULTA habilita un modo de búsqueda con expansión de consulta. Tal modo de búsqueda funciona realizando la búsqueda dos veces y cuando la búsqueda se ejecuta por segunda vez, el conjunto de resultados incluirá algunos de los documentos más relevantes de la primera búsqueda. En general, este modificador es útil cuando el usuario tiene algún conocimiento implícito (por ejemplo, el usuario puede buscar "base de datos" y esperar ver "InnoDB" y "MyISAM" en el conjunto de resultados);
  • El modificador IN BOOLEAN MODE permite buscar con operadores booleanos. Por ejemplo, los operadores +, - o * realizarían cada uno tareas diferentes:el operador + definiría que el valor debe estar presente en una fila, el operador - definiría que el valor no debe existir y el operador * actuaría como un comodín.

Una consulta que usa un índice FULLTEXT se ve así:

SELECT * FROM demo_table WHERE MATCH(demo_field) AGAINST(‘value’ IN NATURAL LANGUAGE MODE);

Recuerde que los índices FULLTEXT son generalmente útiles para operaciones MATCH() AGAINST() - no para operaciones WHERE, lo que significa que si se usara una cláusula WHERE, no se eliminaría la utilidad de usar diferentes tipos de índices.

También vale la pena mencionar que los índices FULLTEXT tienen una longitud mínima de caracteres. En InnoDB, una búsqueda de TEXTO COMPLETO solo se puede realizar cuando la consulta de búsqueda consta de un mínimo de tres caracteres; este límite aumenta a cuatro caracteres en el motor de almacenamiento MyISAM.

Índices DESCENDENTES

Un índice DESCENDENTE es un índice en el que InnoDB almacena las entradas en orden descendente; el optimizador de consultas utilizará dicho índice cuando la consulta solicite un orden descendente. Dicho índice se puede agregar a una columna ejecutando una consulta como la siguiente:

CREATE INDEX descending_index ON demo_table(column_name DESC);

También se puede agregar un índice ascendente a una columna; simplemente reemplace DESC con ASC.

CLAVES PRIMARIAS

UNA CLAVE PRIMARIA sirve como un identificador único para cada fila en una tabla. Una columna con una CLAVE PRINCIPAL debe contener valores únicos; tampoco se permite el uso de valores NULOS. Si se agrega un valor duplicado a una columna que tiene una CLAVE PRIMARIA, MySQL responderá con un error #1062:

#1062 - Duplicate entry ‘Demo’ for key ‘PRIMARY’

Si se agrega un valor NULL a la columna, MySQL responderá con un error #1048:

#1048 - Column ‘id’ cannot be null

Los índices primarios también se denominan a veces índices agrupados (los trataremos más adelante).

También puede crear índices en varias columnas a la vez; estos índices se denominan índices de varias columnas.

Índices de varias columnas

Los índices en varias columnas a menudo se malinterpretan; a veces, los desarrolladores y los administradores de bases de datos indexan todas las columnas por separado o las indexan en el orden incorrecto. Para que las consultas que utilizan índices de varias columnas sean lo más efectivas posible, recuerde que el orden de las columnas en los índices que usan más de una columna es una de las causas más comunes de confusión en este espacio, ya que no hay "por aquí o por la carretera". ” soluciones de orden de índice, debe recordar que el orden correcto de los índices de varias columnas depende de las consultas que utilizan el índice. Si bien esto puede parecer bastante obvio, recuerde que el orden de las columnas es vital cuando se trata de índices de varias columnas:elija el orden de las columnas de manera que sea lo más selectivo posible para las consultas que se ejecutarán con mayor frecuencia.

Para medir la selectividad de columnas específicas, obtenga la relación entre el número de valores indexados distintos y el número total de filas en la tabla; la columna que tenga la selectividad más alta debe ser la primera. .

A veces también necesita indexar columnas de caracteres muy largas y, en ese caso, a menudo puede ahorrar tiempo y recursos al indexar los primeros caracteres (un prefijo) en lugar del valor completo.

Índices de prefijos

Los índices de prefijo pueden ser útiles cuando las columnas contienen valores de cadena muy largos, lo que significaría que agregar un índice en toda la columna consumiría mucho espacio en disco. MySQL ayuda a abordar este problema al permitirle indexar solo un prefijo del valor que, a su vez, hace que el tamaño del índice sea más pequeño. Echa un vistazo:

CREATE TABLE `demo_table` (
`demo_column` VARCHAR(100) NOT NULL,
INDEX(demo_column(10))
);

La consulta anterior crearía un índice de prefijo en la columna de demostración que solo indexa los primeros 10 caracteres del valor. También puede agregar un índice de prefijo a una tabla existente:

CREATE INDEX index_name ON table_name(column_name(length));

Entonces, por ejemplo, si quisiera indexar los primeros 5 caracteres de una columna_demostración en una tabla_demostración, podría ejecutar la siguiente consulta:

CREATE INDEX demo_index ON demo_table(demo_column(5));

Debe elegir un prefijo que sea lo suficientemente largo para dar selectividad, pero también lo suficientemente corto para dar espacio. Sin embargo, puede ser más fácil decirlo que hacerlo:debe experimentar y encontrar la solución que funcione para usted.

Índices de cobertura

Un índice de cobertura "cubre" todos los campos necesarios para ejecutar una consulta. En otras palabras, cuando todos los campos de una consulta están cubiertos por un índice, se está utilizando un índice de cobertura. Por ejemplo, para una consulta como esta:

SELECT id, title FROM demo_table WHERE id = 1;

Un índice de cobertura podría verse así:

INDEX index_name(id, title);

Si desea asegurarse de que una consulta utilice un índice de cobertura, emita una declaración EXPLAIN sobre ella y luego eche un vistazo a la columna Extra. Por ejemplo, si su tabla tiene un índice de varias columnas en id y título y se ejecuta una consulta que accede solo a estas dos columnas, MySQL usará el índice:

mysql> EXPLAIN SELECT id, title FROM demo_table \G;

*************************** 1. row ***************************

<...>

type: index

key: index_name

key_len: 5

rows: 1000

Extra: Using index

<...>

Recuerde que un índice de cobertura debe almacenar los valores de las columnas que cubre. Eso significa que MySQL solo puede usar índices B-Tree para cubrir consultas porque otros tipos de índices no almacenan estos valores.

Índices agrupados, secundarios y cardinalidad de índice

Cuando se analizan los índices, es posible que también escuche los términos índices agrupados, secundarios y cardinalidad del índice. En pocas palabras, los índices agrupados son un enfoque para el almacenamiento de datos y todos los índices que no sean índices agrupados son índices secundarios. La cardinalidad del índice, por otro lado, es el número de valores únicos en un índice.

Un índice agrupado acelera las consultas porque los valores cercanos también se almacenan cerca unos de otros en el disco, pero esa es también la razón por la que solo puede tener un índice agrupado en una tabla.

Un índice secundario es cualquier índice que no es el índice principal. Tal índice puede tener duplicados.

Los inconvenientes de usar índices

El uso de índices ciertamente tiene ventajas, pero no debemos olvidar que los índices también pueden ser una de las principales causas de problemas en MySQL. Algunas de las desventajas de usar índices son las siguientes:

  • Los índices pueden degradar el rendimiento de ciertas consultas; aunque los índices tienden a acelerar el rendimiento de las consultas SELECCIONAR, ralentizan el rendimiento de las consultas INSERTAR, ACTUALIZAR y ELIMINAR porque cuando se actualizan los datos, el índice también debe actualizarse junto con él:cualquier operación que implique manipular los índices será más lenta de lo habitual;
  • Los índices consumen espacio en disco:un índice ocupa su propio espacio, por lo que los datos indexados también consumirán más espacio en disco;
  • Los índices redundantes y duplicados pueden ser un problema:MySQL le permite crear índices duplicados en una columna y no lo "protege" de cometer ese error. Eche un vistazo a este ejemplo: 
    CREATE TABLE `demo_table` (
    
    `id` INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
    
    `column_2` VARCHAR(10) NOT NULL,
    
    `column_3` VARCHAR(10) NOT NULL,
    
    INDEX(id),
    
    UNIQUE(id)
    
    );

Un usuario sin experiencia podría pensar que esta consulta hace que la columna de identificación se incremente automáticamente, luego agrega un índice en la columna y hace que la columna no acepte valores duplicados. Sin embargo, esto no es lo que está sucediendo aquí. En este caso, la misma columna tiene tres índices:un ÍNDICE ordinario, y dado que MySQL implementa las restricciones PRIMARY KEY y UNIQUE con índices, ¡eso agrega dos índices más en la misma columna!

Conclusión

Para concluir, los índices en MySQL tienen su propio lugar:los índices se pueden usar en una multitud de escenarios, pero cada uno de esos escenarios de uso tiene sus propias desventajas que deben tenerse en cuenta para aprovechar al máximo índices que están en uso.

Para usar bien los índices, perfile sus consultas, observe qué opciones tiene cuando se trata de índices, conozca sus ventajas y desventajas, decida qué índices necesita según sus requisitos y después de indexar las columnas, asegúrese de que sus índices estén realmente utilizado por MySQL. Si ha indexado correctamente su esquema, el rendimiento de sus consultas debería mejorar, pero si el tiempo de respuesta no le satisface, vea si se puede crear un mejor índice para mejorarlo.