2010-01-28 14 views
30

Estoy un poco avergonzado de preguntar esto ya que he estado trabajando con MySQL durante años, pero bueno.Índices múltiples e individuales

Tengo una tabla con dos campos, a y b. Me va a correr las siguientes consultas en él:

  • SELECT * FROM ... WHERE A = 1;
  • SELECT * FROM ... WHERE B = 1;
  • SELECT * FROM ... WHERE A = 1 AND B = 1;

Desde el punto de vista del rendimiento, es al menos una de las siguientes configuraciones de los índices más lentos para al menos una consulta? Si es así, por favor elabora.

  1. ALTER TABLE ... ADD INDEX (a); ALTER TABLE ... ADD INDEX (b);
  2. ALTER TABLE ... ADD INDEX (a, b);
  3. ALTER TABLE ... ADD INDEX (a); ALTER TABLE ... ADD INDEX (b); ALTER TABLE ... ADD INDEX (a, b);

Gracias (en cuenta que estamos hablando de los índices no únicos)

Respuesta

27

Sí, al menos uno de los casos es considerablemente más lento. Si sólo se define el siguiente índice:

ALTER TABLE ... ADD INDEX (a, b); 

... SELECT * FROM ... WHERE B = 1; continuación, la consulta no utilizará ese índice.

Cuando crea un índice con una clave compuesta, el orden de las columnas de la clave es importante. Se recomienda intentar ordenar las columnas en la clave para mejorar la selectividad, con las columnas más selectivas a la izquierda de la tecla. Si no hace esto y coloca una columna no selectiva como la primera parte de la clave, corre el riesgo de no utilizar el índice en absoluto. (Fuente: Tips on Optimizing SQL Server Composite Index)

+6

¿Y hay alguna ventaja de ir con la configuración n. ° 3 en lugar de n. ° 1? –

+6

Sí, podría haber una ventaja. Un índice compuesto puede convertirse en un índice de cobertura, cuando todos los datos en la consulta se mantienen dentro del índice mismo. En general, 'SELECT A, B FROM ... WHERE A = 1;', será más rápido si utiliza el índice compuesto en '(A, B)', ya que la consulta no necesitará obtener ningún dato de la tabla . Los datos ya están en el índice. –

+1

Recuerde que los índices ocupan espacio y pueden comprometer un poco el rendimiento en las inserciones y actualizaciones. Me gustaría ir con la opción 3 solo si su aplicación va a hacer consultas que justifiquen el índice adicional ... Consejos sobre un índice de cobertura: http://www.sql-server-performance.com/tips/covering_indexes_p1.aspx –

22

Es muy improbable que la mera existencia de un índice reduzca la velocidad de una consulta SELECT: simplemente no se utilizará.

En teoría, el optimizador puede elegir incorrectamente el índice más largo en (a, b) en lugar de uno en (a) para servir a la consulta que solo busca a.

En la práctica, nunca lo he visto: MySQL generalmente comete el error opuesto, tomando un índice más corto cuando existe uno más largo.

Actualización:

En su caso, cualquiera de las siguientes configuraciones será suficiente para todas las consultas:

(a, b); (b) 

o

(b, a); (a) 

MySQL también puede utilizar dos índices separados con index_intersect, creando estos índices

(a); (b) 

también acelerará la consulta con a = 1 AND b = 1, aunque en menor medida que cualquiera de las soluciones anteriores.

También puede leer este artículo en mi blog:

Actualización 2:

Parece Finalmente entendí tu pregunta :)

ALTER TABLE ... ADD INDEX (a); ALTER TABLE ... ADD INDEX (b); 

Excelente para a = 1 y b = 1, razonablemente bueno para a = 1 AND b = 1

ALTER TABLE ... ADD INDEX (a, b); 

Excelente para a = 1 AND b = 1, casi excelente para a = 1, pobre para b = 1

ALTER TABLE ... ADD INDEX (a); ALTER TABLE ... ADD INDEX (b); ALTER TABLE ... ADD INDEX (a, b); 

excelente para las tres consultas.

+0

Bueno, sí, pero ¿por qué agregar índices innecesarios? –

+1

Creo que está malinterpretando el OP. Pensé que estaba preguntando "¿Es uno de estos más lento que los otros?" no "¿Es uno de estos más lento que no tener ningún índice?" –

4

SQL elegirá el índice que mejor cubra la consulta. un índice en A, B cubrirá la consulta tanto para el caso 1 y 3, pero no para 2 (desde la columna de índice primario es A)

Así que para cubrir las tres preguntas que necesita dos índices:

ALTER TABLE ... ADD INDEX (a, b); ALTER TABLE ... ADD INDEX (b) 
0

Por ejemplo, tiene el conjunto de índices n. ° 3 es óptimo. Mysql elegirá los índices A y B individuales para las cláusulas where de una sola columna, y usará el índice compuesto para la cláusula A & B where.

Cuestiones relacionadas