Lo primero que debes saber es que los índices son una forma de evitar escanear la tabla completa para obtener el resultado que estás buscando.
Hay 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 se devuelva 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 last_name y first_name, el orden en que consulta estos campos importa mucho .
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
columna primero y no es la columna más a la izquierda en el í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, lamentablemente, solo admite el servidor de memoria. Es muy rápido, pero solo es útil para búsquedas completas, lo que significa que no puede usarlo para operaciones como >
, <
o LIKE
.
Dado que solo funciona para el backend de la memoria, probablemente no lo use con mucha frecuencia. El caso principal que se me ocurre en este momento es que creas una tabla temporal en la memoria con un conjunto de resultados de otra selección y realizas muchas otras selecciones en esta tabla temporal usando índices hash.
Si tienes un gran VARCHAR
campo, puede "emular" el uso de un índice hash cuando usa un B-Tree, creando otra columna y guardando un hash del valor grande en ella. 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 usa una función hash como CRC32
o cualquier otra función hash para codificar 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 desde el CRC32
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 hacer un hash de las cosas, incluso si el número de colisión es alto porque solo realizará la segunda comparación (la de cadena) contra los hash repetidos.
Desafortunadamente, al usar esta técnica, aún necesita golpear la mesa para comparar la url
campo.
Resumir
Algunos datos que puede tener en cuenta cada vez que quiera hablar de 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. Puede ilustrarse con 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 es el más usado y es bueno saber el hash, pero puedes encontrar los otros en Documentación de MySQL .
Le recomiendo que lea el libro "MySQL de alto rendimiento", la respuesta anterior definitivamente se basó en su capítulo sobre índices.