2012-03-14 24 views
5

estoy usando la tabla "usuarios", con más de 2 millones de discos. La consulta es:uso del Índice de MySQL para consulta ORDER BY LIMIT

SELECT * FROM users WHERE 1 ORDER BY firstname LIMIT $start,30 

"firstname" column is indexed. Obtener las primeras páginas es muy rápido, mientras que obtener las últimas páginas es muy lento.

que utilizan explicar y aquí están los resultados:

para

EXPLAIN SELECT * FROM `users` WHERE 1 ORDER BY `firstname` LIMIT 10000 , 30 

que estoy recibiendo:

id select_type  table type possible_keys key  key_len  ref  rows Extra 
1 SIMPLE users index NULL firstname 194  NULL 10030 

Pero para

EXPLAIN SELECT * FROM `users` WHERE 1 ORDER BY `firstname` LIMIT 100000 , 30 

estoy recibiendo

id select_type  table type possible_keys key  key_len  ref  rows Extra 
1 SIMPLE users ALL  NULL NULL NULL NULL 2292912  Using filesort 

¿Cuál es el problema?

+0

Demasiada omisión. –

+0

Intente ejecutar la declaración de los usuarios de 'ANALYZE TABLE' y vea si ayuda. –

Respuesta

3

No debe usar limit to page hasta ese momento en su conjunto de datos.

Obtendrá mucho mejores resultados mediante consultas de rango.

SELECT * FROM users 
WHERE firstname >= last_used_name 
ORDER BY firstname 
LIMIT 30 

Dónde last_used_name es uno que se ha visto ya (estoy suponiendo que lo haga el procesamiento por lotes de algún tipo). Obtendrá resultados más precisos si realiza consultas de rango en una columna con índice único. De esta forma, no obtendrás el mismo registro dos veces.

Al hacer

LIMIT 100000 , 30 

MySQL hace esencialmente lo mismo que en

LIMIT 100030 

Sólo que no vuelva primeros 100 miles. Pero los ordena y los lee.

+0

Gracias por la respuesta. Estoy usando esto para paginar la lista. Obtener last_used_name para crear un enlace haría que mi código sea más difícil. Estaría encantado de obtener una buena solución – user1270172

+0

No existe el almuerzo gratis, ya sabes. O optimizas tu código o sufres un 'LIMIT 'lento. Estaré pendiente de esta publicación, quizás surjan otras soluciones. –

0

Para * consultas sin WHERE condición MySQL a menudo no utiliza ningún índice.

La siguiente consulta debería ser mucho más rápido y hacer uso del índice:

SELECT * 
FROM (
    SELECT user_id 
    FROM users 
    WHERE 1 
    ORDER BY firstname 
    LIMIT $start, 30) ids 
JOIN users 
USING (user_id); 

user_id es la clave principal.

Cuestiones relacionadas