137 votos

¿Por qué MYSQL LÍMITE superior de desplazamiento lento de la consulta inicial?

Escenario en resumen: Una tabla con más de 16 millones de registros [2GB]. El LÍMITE superior de compensación con SELECCIONAR el más lento de la consulta se convierte, cuando se utiliza la ORDEN POR *primary_key*

Así que

SELECT * FROM large ORDER BY `id`  LIMIT 0, 30 

tarda mucho menos que

SELECT * FROM large ORDER BY `id` LIMIT 10000, 30 

Que sólo las órdenes de 30 de los registros y del mismo eitherway. Así que no es la sobrecarga de ORDEN.
Ahora, cuando la captura de los últimos 30 filas se tarda alrededor de 180 segundos. ¿Cómo puedo optimizar esa simple consulta?

165voto

Nikos Kyr Puntos 352

Yo tenía el mismo problema que yo. Dado el hecho de que la u quiere a recoger una gran cantidad de datos y no un conjunto específico de 30 u 'll ser probablemente ejecución de un bucle y el incremento de desplazamiento por 30.

Entonces, ¿qué puede hacer en su lugar es:

1)en el último id de un conjunto de datos(30) (por ejemplo, lastId = 530)
2)Añadir la condición "where id > lastId límite de 0,30"

Por lo que u puede tener siempre un desplazamiento del CERO. Usted se sorprenderá por la mejora en el rendimiento.

159voto

Quassnoi Puntos 191041

Es normal que los mayores desplazamientos lentos de la consulta de abajo, desde la consulta necesita para contar la primera OFFSET + LIMIT de los registros (y solo tome LIMIT de ellos). El más alto es este valor, más tiempo se ejecuta la consulta.

La consulta no puede ir a la derecha a OFFSET porque, en primer lugar, los registros pueden ser de diferente longitud, y, en segundo lugar, puede haber lagunas de registros eliminados. Se requiere la comprobación y el recuento de cada registro en su camino.

Suponiendo que id es PRIMARY KEY de MyISAM tabla, se puede acelerar mediante el uso de este truco:

SELECT  t.*
FROM    (
        SELECT  id
        FROM    mytable
        ORDER BY
                id
        LIMIT 10000, 30
        ) q
JOIN    mytable t
ON      t.id = q.id

Consulte este artículo:

15voto

Riedsio Puntos 4500

MySQL no puede ir directamente a la 10000th registro (o el 80000th byte como su sugiriendo) porque no se puede asumir que está lleno ordenados/me gusta (o que tiene valores continuos en 1 a 10000). Aunque pueda ser así en la realidad, MySQL no puede suponer que no hay agujeros/lagunas/eliminado ids.

Así que, como bobs señaló, MySQL va a tener que ir a buscar 10000 filas (o recorrer a través de la 10000th entradas del índice en id) antes de encontrar el 30 para volver.

EDIT : Para ilustrar mi punto

Tenga en cuenta que aunque

SELECT * FROM large ORDER BY id LIMIT 10000, 30 

sería lento(er),

SELECT * FROM large WHERE id >  10000 ORDER BY id LIMIT 30 

sería rápida(er), y volvería a los mismos resultados, siempre que no falten ids (es decir, las lagunas).

5voto

bobs Puntos 12893

El tiempo que consume parte de las dos consultas es recuperar las filas de la tabla. Lógicamente hablando, en la LIMIT 0, 30 versión, sólo el 30 filas necesitan ser recuperados. En la LIMIT 10000, 30 versión, 10000 filas son evaluados y 30 de filas que se devuelven. Puede haber algunas posibilidades de optimización mis datos-proceso de lectura, pero considere lo siguiente:

¿Qué pasa si usted tenía una cláusula where de las consultas? El motor debe devolver todas las filas que cumplen con los requisitos y, a continuación, ordenar los datos, y obtener, finalmente, el 30 de filas.

También considere el caso donde las filas no se procesan en el ORDEN de la secuencia. Todas las filas deben ser ordenados para determinar qué filas que se devuelven.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X