2012-03-22 28 views
13

Tengo una tabla de 200k entradas con columnas de INT. Quiero crear un índice para hacer las consultas más rápido. Esta es la consulta que me gustaría ejecutar: SELECT A,B,C,D,E FROM table WHERE A=23 and (B=45 or C=43). Creé los siguientes índices: B, ACD, C, ABC. Con el comando EXPLAIN encontré que MySQL elige el índice ACD. Así que seguí poblando la tabla con más valores y me di cuenta de que MySQL estaba cambiando entre los índices anteriores (no siempre el mismo).MySQL. Crear un índice para consultas "O"

Dado que hay muchos insertos, tener varios índices causará problemas de rendimiento y podemos suponer que se accede a esta tabla mediante otras consultas que requieren columnas diferentes donde cada índice tiene sentido.

Conozco el USE INDEX(), pero me gustaría saber si debemos confiar en MySQL para elegir el índice correcto.

+2

¿Qué quiere decir con "podemos suponer que esta tabla es accedida por otras consultas que requieren columnas diferentes donde cada ÍNDICE tiene sentido"? ¿Podría dar algunos ejemplos de tales consultas? ¿También puede darnos el resultado de una consulta 'SHOW INDEXES FROM table'? Los índices en A, AB y AC son ciertamente redundantes: estos ya están cubiertos por los índices en ACD/ABC, ABC y ACD, respectivamente. Puede leer sobre cómo maneja MySQL los índices de varias columnas en http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html – Daan

+0

Consulta de ejemplo: 'OBTENER B DE LA tabla WHERE B = 12'. Ok, puedo eliminar A, AB, AC (gracias). Pero aún no explica la razón por la que se usa 'ACD'. Cuando 'D' ni siquiera está en la instrucción' WHERE'. –

+0

Sí, eso es un poco misterioso: el resultado de una consulta 'SHOW INDEXES FROM table' puede ayudar a ver por qué está sucediendo :) – Daan

Respuesta

6

Debido a la OR en la instrucción SQL, MySQL está consiguiendo simplemente el primer índice que incluye A, que es ACD.

Llegué a la conclusión de que la forma de resolver este problema utilizando un INDEX es realizar dos consultas por separado. SELECT A,B,C,D,E FROM table WHERE A=23 AND B=45 que usará INDEX ABC y luego SELECT A,B,C,D,E FROM table WHERE A=23 AND C=43 que usará INDEX ACD. Todo esto se puede hacer en un solo paso con (...) UNION (...), que resulta ser más rápido y solo utiliza INDEX.

1

Mysql solo puede usar la parte 'más a la izquierda' de un índice compuesto. Es decir, si su cláusula donde se ve como

WHERE A=1 AND B=2 

continuación, MySQL puede utilizar un índice en A o AB, pero AB sería lo mejor. ACB no se pudo utilizar ya que el índice está dividido por otra columna

Con su cláusula WHERE dada, no creo que el motor de consulta MySQL pueda utilizar varios índices. Haría un AB y AC y usar FORCE INDEX, ver cuál es más rápido.

Una clave compuesta de tres columnas no ayudará en este caso ya que está buscando una A y otra columna. Este tipo de clave ayudaría si su consulta utilizara AND en lugar de OR. Un índice en ABC sería útil para

WHERE A=1 AND B=2 AND C=3 
+2

Sí, con 'AND' utiliza la consulta ABC como se esperaba. Usar 'A',' AB', 'AC' sería redundante como lo menciona @Daan en el comentario anterior. De la documentación de MySQL: "El optimizador puede usar cualquier prefijo que esté más a la izquierda del índice para buscar filas." ÍNDICE "en (col1, col2, col3), tiene capacidades de búsqueda indexadas en (col1), (col1, col2) y (col1, col2, col3) ". –

+1

Esta es una pregunta sobre O, no AND. –