2009-08-09 19 views
29

Esta es una pregunta que he tenido para siempre.Índices de MySQL y orden

Por lo que sé, el orden de los índices importa. Entonces, un índice como [first_name, last_name] no es lo mismo que [last_name, first_name], ¿verdad?

Si sólo definir el primer índice, significa que sólo será utilizado para

SELECT * FROM table WHERE first_name="john" AND last_name="doe"; 

y no para

SELECT * FROM table WHERE last_name="doe" AND first_name="john"; 

Desde que estoy usando un ORM, no tengo ni idea de qué orden se van a llamar estas columnas. ¿Eso significa que tengo que agregar índices en todas las permutaciones? Eso es factible si tengo un índice de 2 columnas, pero ¿qué sucede si mi índice está en 3 o 4 columnas?

Respuesta

44

El orden del índice importa cuando las condiciones de su consulta solo se aplican a PARTE del índice. Considere:

  1. SELECT * FROM table WHERE first_name="john" AND last_name="doe"

  2. SELECT * FROM table WHERE first_name="john"

  3. SELECT * FROM table WHERE last_name="doe"

Si el índice es (first_name, last_name) consultas de 1 y 2 de la usarán, consulta # 3 de won 't. Si su índice es (last_name, first_name) las consultas 1 y 3 lo usarán, la consulta n.º 2 no lo hará. Cambiar el orden de condición dentro de la cláusula WHERE no tiene ningún efecto en ningún caso.

detalles son here

actualización:
En caso de que lo anterior no está claro - MySQL sólo puede utilizar un índice si las columnas en condiciones de consulta forman un prefijo a la izquierda del índice. La consulta n.º 2 anterior no puede usar (last_name, first_name) índice porque solo se basa en first_name y first_name NO es el prefijo situado más a la izquierda del índice (last_name, first_name).

El orden de las condiciones DENTRO de la consulta no es importante; la consulta n. ° 1 anterior podrá usar el índice (last_name, first_name) muy bien porque sus condiciones son first_name y last_name y, juntas, forman un prefijo a la izquierda del índice (last_name, first_name).

+0

Supongo que SELECCIONAR * FROM tabla WHERE last_name = "doe" Y first_name = "john" no? Si ese es el caso, dado que mi ORM oculta toda la creación de consultas, probablemente tenga que definir los 2 índices ... lo que realmente apesta, porque tengo un índice en 3 columnas para definir ... –

+1

No, has malentendido. DONDE 'last_name' =" doe "Y' first_name' = "john" la consulta usaría cualquiera de los índices ('first_name',' last_name') o ('last_name',' first_name') bien. – ChssPly76

+0

Una pregunta: para una consulta con 2 condiciones AND, ¿es importante, velocidad, si el índice se "revierte" en comparación con las condiciones de la consulta, o no? ¿O depende de la cardinalidad de esas columnas? – Mihai

5

ChssPly76 es correcto en que el orden de las expresiones booleanas no tiene que coincidir con el orden de las columnas en el índice. Los operadores booleanos son commutative, y el optimizador de MySQL es lo suficientemente inteligente como para saber cómo hacer coincidir la expresión con el índice en la mayoría de los casos.

También quiero agregar que debe aprender a usar la característica EXPLAIN de MySQL para que pueda ver por sí mismo qué índices elegirá el optimizador para una consulta determinada.

+2

+1 para explicar. – Petrogad

+0

MySQL Workbench muestra una representación gráfica de la información 'EXPLAIN' en' Plan de ejecución'. –

2

Por qué no extender la respuesta un poco para hacer que todo sea completamente claro a la vez.

Si la tabla tiene un índice de varias columnas, el optimizador puede usar cualquier prefijo situado más a la izquierda del índice para buscar filas. Por ejemplo, si tiene un índice de tres columnas en (col1, col2, col3), tiene capacidades de búsqueda indexadas en (col1), (col1, col2) y (col1, col2, col3).

MySQL no puede usar un índice si las columnas no forman un prefijo situado más a la izquierda del índice. Suponga que tiene las instrucciones SELECT que se muestran aquí:

SELECT * FROM tbl_name WHERE col1=val1; 
SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2; 

SELECT * FROM tbl_name WHERE col2=val2; 
SELECT * FROM tbl_name WHERE col2=val2 AND col3=val3; 

Si existe un índice de (col1, col2, col3), solamente las dos primeras consultas utilizan el índice. La tercera y cuarta consulta involucran columnas indexadas, pero (col2) y (col2, col3) no son prefijos de más a la izquierda de (col1, col2, col3). - MySQL dev

Cuestiones relacionadas