2010-05-02 15 views
10

Tengo una consulta increíblemente simple (tipo de tabla InnoDb) y EXPLAIN dice que MySQL debe hacer un pase adicional para descubrir cómo recuperar las filas en orden ordenado.¿Alguna manera de evitar una clasificación de archivos cuando la orden es diferente de la cláusula where?

SELECT * FROM `comments` 
WHERE (commentable_id = 1976) 
ORDER BY created_at desc LIMIT 0, 5 

explicar exacta de salida:

table select_type  type extra       possible_keys key    key length ref  rows 
comments simple  ref using where; using filesort common_lookups common_lookups 5 const 89 

commentable_id está indexado. Los comentarios no tienen nada de truco, solo un campo de contenido.

El manual sugiere que si el orden por es diferente de where, no hay manera de evitar el archivo.

http://dev.mysql.com/doc/refman/5.0/en/order-by-optimization.html

También probé el fin de Identificación, así como que es equivalente, pero no hace ninguna diferencia, incluso si añado Identificación como un índice (que entiendo que no se requiere como ID está indexado de forma implícita en MySQL).

¡gracias de antemano por cualquier idea!

para marcar - aquí está SHOW CREATE TABLE

CREATE TABLE `comments` (
    `id` int(11) NOT NULL auto_increment, 
    `user_id` int(11) default NULL, 
    `commentable_type` varchar(255) default NULL, 
    `commentable_id` int(11) default NULL, 
    `content` text, 
    `created_at` datetime default NULL, 
    `updated_at` datetime default NULL, 
    `hidden` tinyint(1) default '0', 
    `public` tinyint(1) default '1', 
    `access_point` int(11) default '0', 
    `item_id` int(11) default NULL, 
    PRIMARY KEY (`id`), 
    KEY `created_at` (`created_at`), 
    KEY `common_lookups` (`commentable_id`,`commentable_type`,`hidden`,`created_at`,`public`), 
    KEY `index_comments_on_item_id` (`item_id`), 
    KEY `index_comments_on_item_id_and_created_at` (`item_id`,`created_at`), 
    KEY `index_comments_on_user_id` (`user_id`), 
    KEY `id` (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=31803 DEFAULT CHARSET=latin1 
+0

+1 para usar Explique primero, aunque honestamente no puedo decir que entiendo completamente cómo descifrar una declaración de Explicación. Tendrá que resolver eso uno de estos días. :) –

+1

¿Puedes publicar también la salida de los comentarios de 'SHOW CREATE TABLE'? –

+1

@Robert Harvey: Pruebe la excelente presentación de Baron Schwartz: http://www.percona.com/files/presentations/EXPLAIN_demystified.pdf –

Respuesta

3

Tenga en cuenta que el término MySQL filesort no significa necesariamente que se escribe en el disco. Simplemente significa que va a ordenar sin usar un índice. Si el conjunto de resultados es lo suficientemente pequeño, MySQL lo clasificará en la memoria, que es órdenes de magnitud más rápido que la E/S de disco.

Puede aumentar la cantidad de memoria asignada por MySQL para filesorts en memoria usando la variable de servidor sort_buffer_size. En MySQL 5.1, el tamaño del búfer de clasificación predeterminado es de 2 MB, y el máximo que puede asignar es de 4 GB.


actualización: Con respecto al comentario de Jonathan Leffler sobre la medición de cuánto tiempo tarda la clasificación, se puede aprender a utilizar SHOW PROFILE FOR QUERY que le dará el desglose de cuánto tiempo toma cada fase de ejecución de la consulta.

+0

Gracias Bill. Mantendré en mente sort_buffer_size definitivamente ya que el salto desde la memoria al disco seguramente tendrá un gran éxito y necesito hacer algunas pruebas de carga graduada para ver dónde se encuentran estos codos ... –

+0

show profile y set profiling = 1 obsoleto en las versiones actuales. – Ross

+0

@Ross, buen punto, la nueva forma de hacerlo es con PERFORMANCE_SCHEMA. Pero para ser justos, SHOW PROFILE está en desuso en MySQL 5.6.7 y más tarde. MySQL 5.5 todavía es una versión actual hoy. –

2

trate de añadir un índice combinado de (commentable_id, created_at).

Cuestiones relacionadas