Lo primero que debe saber es que los índices son una forma de evitar escanear la tabla completa para obtener el resultado que está buscando.
Existen diferentes tipos de índices y se implementan en la capa de almacenamiento, por lo que no hay un estándar entre ellos y también dependen del motor de almacenamiento que esté utilizando.
InnoDB y el índice B + Tree
Para InnoDB, el tipo de índice más común es el índice basado en B + Tree, que almacena los elementos en un orden ordenado. Además, no tiene que acceder a la tabla real para obtener los valores indexados, lo que hace que su consulta regrese mucho más rápido.
El "problema" de este tipo de índice es que debe consultar el valor más a la izquierda para usar el índice. Entonces, si su índice tiene dos columnas, digamos apellido y nombre, el orden en que consulta estos campos es muy importante .
Entonces, dada la siguiente tabla:
CREATE TABLE person (
last_name VARCHAR(50) NOT NULL,
first_name VARCHAR(50) NOT NULL,
INDEX (last_name, first_name)
);
Esta consulta aprovecharía el índice:
SELECT last_name, first_name FROM person
WHERE last_name = "John" AND first_name LIKE "J%"
Pero el siguiente no
SELECT last_name, first_name FROM person WHERE first_name = "Constantine"
Porque estás consultando el first_name
primero columna y no es la columna más a la izquierda del índice.
Este último ejemplo es aún peor:
SELECT last_name, first_name FROM person WHERE first_name LIKE "%Constantine"
Porque ahora, está comparando la parte más a la derecha del campo más a la derecha en el índice.
El índice hash
Este es un tipo de índice diferente que desafortunadamente solo admite el backend de memoria. Es increíblemente rápido, pero solo es útil para búsquedas completas, lo que significa que no puede usarlo para operaciones como >
, <
oLIKE
.
Dado que solo funciona para el backend de memoria, probablemente no lo use con mucha frecuencia. El caso principal que se me ocurre en este momento es el que crea una tabla temporal en la memoria con un conjunto de resultados de otra selección y realiza muchas otras selecciones en esta tabla temporal utilizando índices hash.
Si tiene un VARCHAR
campo grande , puede "emular" el uso de un índice hash cuando usa un B-Tree, creando otra columna y guardando un hash del gran valor en él. Digamos que está almacenando una URL en un campo y los valores son bastante grandes. También puede crear un campo entero llamado url_hash
y usar una función hash como CRC32
o cualquier otra función hash para hacer hash de la URL al insertarla. Y luego, cuando necesite consultar este valor, puede hacer algo como esto:
SELECT url FROM url_table WHERE url_hash=CRC32("http://gnu.org");
El problema con el ejemplo anterior es que, dado que la CRC32
función genera un hash bastante pequeño, terminará con muchas colisiones en los valores hash. Si necesita valores exactos, puede solucionar este problema haciendo lo siguiente:
SELECT url FROM url_table
WHERE url_hash=CRC32("http://gnu.org") AND url="http://gnu.org";
Todavía vale la pena analizar las cosas, incluso si el número de colisión es alto porque solo realizará la segunda comparación (la cadena) contra los hashes repetidos.
Desafortunadamente, usando esta técnica, aún necesita golpear la tabla para comparar el url
campo.
Envolver
Algunos hechos que puede considerar cada vez que quiera hablar sobre la optimización:
La comparación de enteros es mucho más rápida que la comparación de cadenas. Se puede ilustrar con el ejemplo sobre la emulación del índice hash en InnoDB
.
Tal vez, agregar pasos adicionales en un proceso lo hace más rápido, no más lento. Se puede ilustrar por el hecho de que puede optimizar un SELECT
dividiéndolo en dos pasos, haciendo que el primero almacene valores en una tabla en memoria recién creada y luego ejecute las consultas más pesadas en esta segunda tabla.
MySQL también tiene otros índices, pero creo que el B + Tree uno es el más utilizado y el hash es bueno, pero puede encontrar los otros en la documentación de MySQL .
Le recomiendo que lea el libro "High Performance MySQL", la respuesta anterior se basó definitivamente en su capítulo sobre índices.