2009-12-23 5 views
6

Tengo una tabla que tiene una clave externa a una tabla que almacena algunos datos de blobs. Cuando hago una combinación interna en las tablas con una condición en la tabla principal, el tipo de unión va de 'índice' a 'TODO'. Me gustaría evitar esto ya que mi tabla de blobs está en el orden de decenas de gigabytes. ¿Cómo puedo evitarlo?¿Cómo evito un escaneo de tabla completo con esta combinación interna básica?

Aquí es unirse a la del interior básica:

EXPLAIN SELECT m.id, b.id, b.data 
     FROM metadata m, blobstore b 
     WHERE m.fkBlob = b.id; 

1, 'SIMPLE', 'm', 'index', 'fk_blob', 'fk_blob', '4', '', 1, 'Using index' 
1, 'SIMPLE', 'b', 'eq_ref', 'PRIMARY', 'PRIMARY', '4', 'blob_index.m.fkBlob', 1, '' 

Aquí añado una condición en la mesa principal:

EXPLAIN SELECT m.id, b.id, b.data 
     FROM metadata m, blobstore b 
     WHERE m.fkBlob = b.id AND m.start < '2009-01-01'; 
1, 'SIMPLE', 'b', 'ALL', 'PRIMARY', '', '', '', 1, '' 
1, 'SIMPLE', 'm', 'ref', 'fk_blob,index_start', 'fk_blob', '4', 'blob_index.b.id', 1, 'Using where' 

en cuenta que el orden en que se enumeran las tablas ha cambiado. Ahora está haciendo un escaneo de tabla completo en la tabla de blob debido a una condición que he agregado con respecto a la tabla principal.

Aquí es el esquema:

DROP TABLE IF EXISTS `blob_index`.`metadata`; 
    CREATE TABLE `blob_index`.`metadata` (
     `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
     `fkBlob` int(10) unsigned NOT NULL, 
     `start` datetime NOT NULL, 
     PRIMARY KEY (`id`), 
     KEY `fk_blob` (`fkBlob`), 
     KEY `index_start` (`start`), 
     CONSTRAINT `fk_blob` FOREIGN KEY (`fkBlob`) REFERENCES `blobstore` (`id`) 
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 


    DROP TABLE IF EXISTS `blob_index`.`blobstore`; 
    CREATE TABLE `blob_index`.`blobstore` (
     `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
     `data` mediumblob NOT NULL, 
     PRIMARY KEY (`id`) 
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

Respuesta

3

Creo que se está tratando esta en la mesa de vacío (ya que MySQL piensa que tiene que pasar por una fila de hacer escaneo completo de tabla), lo que podría influir en los resultados del planificador. Cuando lo haga en la tabla real, los resultados de EXPLAIN pueden variar (y de hecho variaron en mi prueba).

+0

Tu derecho, arrojé algunos datos allí, ejecuté la tabla de análisis en ambas tablas, y ahora la primera combinación es de tipo rango en la tabla meta. – Fredrick

0

Si leo lo que ha publicado correctamente va de index a ref y eq_ref a all.

CREATE INDEX idx_metadata USING BTREE ON `metadata` (fkBlob,start); 

Debería llevarlo de vuelta.

3

El optimizador cree que la consulta se beneficiará al intercambiar el orden de las tablas (lo que probablemente significa que las estadísticas no están actualizadas).

Usted puede tratar de añadir un índice en metadata (start, fkBlob):

CREATE INDEX ix_metadata_start_blob ON metadata (start, fkBlob) 

y ejecutar ANALYZE TABLE en ambas mesas.

De esta manera, el índice en start se utilizará para filtrar en metadata que se convertirá en líder.

También puede forzar explícitamente el orden de la unión:

SELECT * 
FROM metadata m 
STRAIGHT_JOIN 
     blobstore b 
ON  b.id = m.fkBlob 
WHERE m.start <= '2009-01-01' 

, aunque por lo general no es recomendable.

0
if the index doesnot take it right use HINTS 

select /* INDEX <index_name> */ 
blah blah blah 
from ........ 
0

En el primer ejemplo, MySQL utiliza el índice de metadatos fk_blob porque era un índice de cobertura - cada columna se utiliza en la consulta estuvo presente en el índice. (Esto es lo que significa "usar índice"). Esa consulta aún realizó un escaneo completo, pero escaneó cada fila a través del índice secundario en lugar del primario. Tan pronto como utilizó el inicio, perdió el índice de cobertura y MySQL calculó que era más rápido usar blobstore como el índice de conducción. (El índice principal de InnoDB está integrado con el almacenamiento de fila.)

Si desea que MySQL continúe utilizando un índice de metadatos como índice de conducción, asegúrese de que haya un solo índice que sea útil para la consulta. Un índice en (inicio, fkBlob) sería lo mejor para la segunda consulta, pero puede no ser útil para otras consultas. El siguiente mejor índice es reemplazar (fkBlob) con (fkBlob, inicio).Deberá equilibrar tener demasiados índices (que son caros de mantener) frente a tener planes de consulta eficientes. Prueba, prueba, prueba y nunca creas a ciegas en tu base de datos de desarrollo.

Cuestiones relacionadas