He estado usando índices en mis bases de datos MySQL durante un tiempo, pero nunca aprendí correctamente sobre ellos. Generalmente pongo un índice en cualquier campo que buscaré o seleccionaré usando una WHERE
cláusula, pero a veces no parece tan en blanco y negro.
¿Cuáles son las mejores prácticas para los índices MySQL?
Ejemplos de situaciones / dilemas:
Si una tabla tiene seis columnas y todas se pueden buscar, ¿debo indexarlas todas o ninguna?
¿Cuáles son los impactos negativos en el rendimiento de la indexación?
Si tengo una columna VARCHAR 2500 que se puede buscar desde partes de mi sitio, ¿debo indexarla?
mysql
indexing
query-optimization
Haroldo
fuente
fuente
Respuestas:
Definitivamente deberías pasar un tiempo leyendo sobre indexación, hay mucho escrito al respecto y es importante entender lo que está sucediendo.
En términos generales, un índice impone un orden en las filas de una tabla.
Por simplicidad, imagine que una tabla es solo un gran archivo CSV. Cada vez que se inserta una fila, se inserta al final . Por lo tanto, el orden "natural" de la tabla es solo el orden en que se insertaron las filas.
Imagine que tiene ese archivo CSV cargado en una aplicación de hoja de cálculo muy rudimentaria. Todo lo que hace esta hoja de cálculo es mostrar los datos y numerar las filas en orden secuencial.
Ahora imagine que necesita encontrar todas las filas que tienen algún valor "M" en la tercera columna. Dado lo que tiene disponible, solo tiene una opción. Escanea la tabla verificando el valor de la tercera columna para cada fila. Si tiene muchas filas, ¡este método (un "escaneo de tabla") puede llevar mucho tiempo!
Ahora imagine que además de esta tabla, tiene un índice. Este índice particular es el índice de valores en la tercera columna. El índice enumera todos los valores de la tercera columna, en un orden significativo (por ejemplo, alfabéticamente) y para cada uno de ellos, proporciona una lista de números de fila donde aparece ese valor.
Ahora tiene una buena estrategia para encontrar todas las filas donde el valor de la tercera columna es "M". Por ejemplo, puede realizar una búsqueda binaria ! Mientras que el escaneo de la tabla requiere que busque N filas (donde N es el número de filas), la búsqueda binaria solo requiere que observe las entradas de índice log-n, en el peor de los casos. ¡Vaya, eso es mucho más fácil!
Por supuesto, si tiene este índice y agrega filas a la tabla (al final, ya que así es como funciona nuestra tabla conceptual), debe actualizar el índice cada vez. Así que trabajas un poco más mientras escribes nuevas filas, pero ahorras un montón de tiempo cuando buscas algo.
Entonces, en general, la indexación crea una compensación entre la eficiencia de lectura y la eficiencia de escritura. Sin índices, las inserciones pueden ser muy rápidas: el motor de la base de datos simplemente agrega una fila a la tabla. A medida que agrega índices, el motor debe actualizar cada índice mientras realiza la inserción.
Por otro lado, las lecturas se vuelven mucho más rápidas.
Con suerte, eso cubre sus dos primeras preguntas (como han respondido otros, debe encontrar el equilibrio correcto).
Tu tercer escenario es un poco más complicado. Si usa LIKE, los motores de indexación generalmente lo ayudarán con su velocidad de lectura hasta el primer "%". En otras palabras, si está SELECCIONANDO DONDE la columna COMO 'foo% bar%', la base de datos usará el índice para encontrar todas las filas donde la columna comienza con "foo", y luego deberá escanear ese conjunto de filas intermedio para encontrar el subconjunto que contiene "barra". SELECCIONAR ... DONDE la columna COMO '% bar%' no puede usar el índice. Espero que puedas ver por qué.
Finalmente, debe comenzar a pensar en los índices en más de una columna. El concepto es el mismo y se comporta de manera similar al material LIKE: esencialmente, si tiene un índice en (a, b, c), el motor continuará usando el índice de izquierda a derecha lo mejor que pueda. Entonces, una búsqueda en la columna a podría usar el índice (a, b, c), como lo haría uno en (a, b). Sin embargo, el motor necesitaría hacer un escaneo completo de la tabla si estuviera buscando DONDE b = 5 AND c = 1)
Espero que esto ayude a arrojar un poco de luz, pero debo reiterar que es mejor pasar unas horas buscando buenos artículos que expliquen estas cosas en profundidad. También es una buena idea leer la documentación de su servidor de base de datos particular. La forma en que los planificadores de consultas implementan y utilizan los índices puede variar bastante.
fuente
FULLTEXT
índices? ¿Pueden ayudar con condiciones comoLIKE '%bar%'
?FULLTEXT
puede ayudar con esa consulta sibar
es una "palabra".FULLTEXT
maneja palabras, no subcadenas arbitrarias (como loLIKE
hace).Echa un vistazo a presentaciones como Más Dominio del arte de la indexación .
Actualización 12/2012: He publicado una nueva presentación mía: Cómo diseñar índices, de verdad . Lo presenté en octubre de 2012 en ZendCon en Santa Clara, y en diciembre de 2012 en Percona Live London.
Diseñar los mejores índices es un proceso que tiene que coincidir con las consultas que ejecuta en su aplicación.
Es difícil recomendar reglas de propósito general sobre qué columnas son mejores para indexar, o si debe indexar todas las columnas, sin columnas, qué índices deben abarcar varias columnas, etc. Depende de las consultas que necesite ejecutar.
Sí, hay algunos gastos generales, por lo que no debe crear índices innecesariamente. Pero debe crear los índices que brinden beneficios a las consultas que necesita para ejecutarse rápidamente. La sobrecarga de un índice generalmente es mucho mayor que su beneficio.
Para una columna que es VARCHAR (2500), probablemente desee utilizar un índice FULLTEXT o un índice de prefijo:
Tenga en cuenta que un índice convencional no puede ayudar si está buscando palabras que pueden estar en el medio de ese varchar largo. Para eso, use un índice de texto completo.
fuente
No repetiré algunos de los buenos consejos en otras respuestas, pero agregaré:
Índices compuestos
Puede crear índices compuestos, un índice que incluye varias columnas. MySQL puede usarlos de izquierda a derecha . Entonces si tienes:
Si tiene un índice compuesto que incluye Nombre / Categoría / Edad en ese orden, estas cláusulas WHERE usarían el índice:
pero
no usaría ese índice porque todo tiene que usarse de izquierda a derecha.
Explique
Use Explain / Explain Extended para comprender qué índices están disponibles para MySQL y cuál realmente selecciona. MySQL solo usará UNA clave por consulta .
Registro de consulta lenta
Active el registro de consultas lentas para ver qué consultas se ejecutan lentamente.
Columnas anchas
Si tiene una columna ancha donde la MAYOR parte de la distinción ocurre en los primeros caracteres, puede usar solo los primeros N caracteres en su índice. Ejemplo: tenemos una columna ReferenceNumber definida como varchar (255) pero el 97% de los casos, el número de referencia es de 10 caracteres o menos. Cambié el índice para mirar solo los primeros 10 caracteres y mejoré bastante el rendimiento.
fuente
¿Está buscando campo por campo o algunas búsquedas utilizan múltiples campos? Los campos que están más que se busca en? ¿Cuáles son los tipos de campo? (El índice funciona mejor en INT que en VARCHAR por ejemplo) ¿Ha intentado usar EXPLAIN en las consultas que se están ejecutando?
ACTUALIZACIONES e INSERTOS serán más lentos. También hay requisitos adicionales de espacio de almacenamiento, pero eso no es habitual en estos días.
No, a menos que sea ÚNICO (lo que significa que ya está indexado) o solo busque coincidencias exactas en ese campo (sin usar LIKE o la búsqueda de texto completo de mySQL).
Normalmente indexaría los campos que son los más consultados, y luego los INT / BOOLEAN / ENUM en lugar de los campos que son VARCHARS. No olvide, a menudo necesita crear un índice en campos combinados, en lugar de un índice en un campo individual. Use EXPLAIN y verifique el registro lento.
fuente
Cargue datos de manera eficiente : los índices aceleran las recuperaciones pero ralentizan las inserciones y eliminaciones, así como las actualizaciones de valores en columnas indexadas. Es decir, los índices ralentizan la mayoría de las operaciones que implican escritura. Esto ocurre porque escribir una fila requiere escribir no solo la fila de datos, también requiere cambios en cualquier índice. Cuantos más índices tenga una tabla, más cambios deben realizarse y mayor es la degradación del rendimiento promedio. La mayoría de las tablas reciben muchas lecturas y pocas escrituras, pero para una tabla con un alto porcentaje de escrituras, el costo de la actualización del índice puede ser significativo.
Evite los índices : si no necesita un índice particular para que las consultas funcionen mejor, no lo cree.
Espacio en disco : un índice ocupa espacio en disco, y varios índices ocupan correspondientemente más espacio. Esto podría hacer que alcance un límite de tamaño de tabla más rápidamente que si no hubiera índices. Evite los índices siempre que sea posible.
Para llevar: no sobrepasar el índice
fuente
En general, los índices ayudan a acelerar la búsqueda en la base de datos, teniendo la desventaja de usar espacio extra en el disco y ralentizar las consultas
INSERT
/UPDATE
/DELETE
. UseEXPLAIN
y lea los resultados para saber cuándo MySQL usa sus índices.La indexación de las seis columnas no siempre es la mejor práctica.
(a) ¿Va a utilizar alguna de esas columnas cuando busque información específica?
(b) ¿Cuál es la selectividad de esas columnas (cuántos valores distintos hay almacenados, en comparación con la cantidad total de registros en la tabla)?
MySQL utiliza un optimizador basado en costos, que intenta encontrar la ruta "más barata" al realizar una consulta. Y los campos con baja selectividad no son buenos candidatos.
Ya respondió: espacio extra en disco, menor rendimiento durante la inserción - actualización - eliminación.
Pruebe el índice FULLTEXT .
fuente
1/2) Los índices aceleran ciertas operaciones de selección, pero ralentizan otras operaciones como insertar, actualizar y eliminar. Puede ser un buen equilibrio.
3) use un índice de texto completo o quizás una esfinge
fuente
slow down other operations like insert, update and deletes
, puede usar elSTART TRANSACTION;
YOUR CODE HERE;
COMMIT
cual puede ayudar a evitarslowing down
las otras operaciones, ya que solo verificará una vez las restricciones. PRECAUCIÓN: Si usaREPLACE INTO
y suSQL_MODE
<>STRICT_ALL_TABLES
OTRADITIONAL
ElBulk Load
ignorará el reemplazo e insertará duplicados.