2010-01-12 10 views
6

Un colega me pidió que explicara cómo los índices (índices) aumentan el rendimiento; Intenté hacerlo, pero me confundí.
Utilicé el modelo a continuación para la explicación (una base de datos de registro de errores/diagnósticos). Se compone de tres tablas:¿Se requiere un índice compuesto para acelerar la consulta combinada?

  • Lista de los sistemas de negocio, mesa de "sistema" que contiene sus nombres
  • Lista de diferentes tipos de huellas, "TraceTypes" mesa, definiendo qué tipos de mensajes de error puede estar conectado a
  • mensajes de seguimiento actuales, que tienen las claves externas de System y TraceTypes tablas

he usado MySQL para la demo, sin embargo, no recuerdo los tipos de tabla que utilicé. Creo que fue InnoDB.

System        TraceTypes 
-----------------------------   ------------------------------------------ 
| ID   | Name  |   | ID | Code | Description   | 
-----------------------------   ------------------------------------------ 
| 1   | billing  |   | 1  | Info | Informational mesage | 
| 2   | hr   |   | 2  | Warning| Warning only   | 
-----------------------------   | 3  | Error | Failure    | 
      |       ------------------------------------------ 
      |    ------------| 
Traces |    |    
-------------------------------------------------- 
| ID | System_ID | TraceTypes_ID | Message  | 
-------------------------------------------------- 
| 1 | 1  | 1   | Job starting | 
| 2 | 1  | 3   | System.nullr..| 
-------------------------------------------------- 

En primer lugar, he añadido algunos registros a todas las tablas y demostró que la consulta a continuación se ejecuta en 0.005 segundos:

select count(*) from Traces 
    inner join System on Traces.System_ID = System.ID 
    inner join TraceTypes on Traces.TraceTypes_ID = TraceTypes.ID 
where 
    System.Name='billing' and TraceTypes.Code = 'Info' 

Entonces me genera más datos (no hay índices aún)

  • "Sistema" contenía aproximadamente 100 entradas
  • "Tipo de traza" contenía aproximadamente 50 entradas
  • "Huellas" contenía ~ 10 millones de registros.

Ahora la consulta anterior tomó 8-10 segundos.

Creé índices en la columna Traces.System_ID y en la columna Traces.TraceTypes_ID. Ahora esta consulta ejecutada en milisegundos:

select count(*) from Traces where System_id=1 and TraceTypes_ID=1; 

Esto también fue rápido:

select count(*) from Traces 
    inner join System on Traces.System_ID = System.ID 
where System.Name='billing' and TraceTypes_ID=1; 

pero la consulta anterior, que se unió a las tres mesas todavía tardó 8-10 segundos en completarse.

Solo cuando creé un índice compuesto (columnas System_ID y TraceTypes_ID incluidas en el índice), la velocidad disminuyó a milisegundos.

La afirmación básica que me enseñaron antes es "todas las columnas que usa para unir, debe estar indexada".
Sin embargo, en mi escenario tenía índices tanto en System_ID y TraceTypes_ID, sin embargo, MySQL no los usó. La pregunta es, ¿por qué? Mis apuestas son: la relación de recuento de elementos 100: 10,000,000: 50 hace que los índices de una sola columna sean demasiado grandes para ser utilizados. ¿Pero es verdad?

Respuesta

2

En primer lugar, la manera correcta y más fácil de analizar una declaración SQL lenta es hacer EXPLAIN. Descubra cómo el optimizador eligió su plan y reflexione sobre por qué y cómo mejorarlo. Sugeriría estudiar los resultados de EXPLAIN con solo 2 índices separados para ver cómo mysql ejecuta su declaración.

No estoy muy familiarizado con MySQL, pero parece que hay restricciones de MySQL 4 de usar solo un índice por tabla involucrado en una consulta. Parece que hay mejoras en esto desde MySQL 5 (index merge), pero no estoy seguro de si se aplica a su caso. Nuevamente, EXPLAIN debería decirle la verdad.

Incluso con el uso de 2 índices por tabla permitida (MySQL 5), el uso de 2 índices separados suele ser más lento que el índice compuesto. El uso de 2 índices separados requiere un paso de fusión de índice, en comparación con el paso único de usar un índice compuesto.

Multi Column indexes vs Index Merge podría ser útil, que utiliza MySQL 5.4.2.

+0

tahnk usted, nunca supe de tal "regla de un índice por tabla", pero parece ser lógico y también - para explicar mi problema (yo estaba en mysql5.4.algo, sin embargo). – naivists

0

Supongo que usaría el índice y luego podría usar la búsqueda tradicional para pasar a otro índice y luego filtrar. Por favor revisa el plan de ejecución. En resumen, podría estar recorriendo dos índices en un bucle anidado. Según mi entendimiento. Deberíamos tratar de hacer un índice compuesto en la columna que esté filtrando o uniendo y luego deberíamos usar la cláusula Incluir para las columnas que están en la selección. Nunca he trabajado en MySql, así que mi comprensión se basa en SQL Server 2005.

1

No es tanto el tamaño de los índices como la selectividad lo que determina si el optimizador los usará.

Cuestiones relacionadas