sql >> Base de Datos >  >> RDS >> PostgreSQL

Seleccionar consulta con límite de desplazamiento es demasiado lento

Es lento porque necesita ubicar el offset superior filas y escanear las siguientes 100. Ninguna cantidad de optimización cambiará eso cuando se trata de grandes compensaciones.

Esto se debe a que su consulta literalmente instruir el motor DB para visitar muchas filas usando offset 3900000 -- Eso es 3,9 millones de filas. Las opciones para acelerar esto no son muchas.

La RAM súper rápida, los SSD, etc. ayudarán. Pero solo ganará por un factor constante al hacerlo, lo que significa que simplemente está pateando la lata por el camino hasta que alcance una compensación lo suficientemente grande.

Asegurarse de que la tabla quepa en la memoria, con mucho más de sobra, también ayudará en un factor constante más grande, excepto la primera vez. Pero esto puede no ser posible con una tabla o índice lo suficientemente grande.

Asegurarse de que está haciendo escaneos de solo índice funcionará hasta cierto punto. (Vea la respuesta de velis; tiene mucho mérito). El problema aquí es que, para todos los propósitos prácticos, puede pensar en un índice como una tabla que almacena una ubicación de disco y los campos indexados. (Está más optimizado que eso, pero es una primera aproximación razonable). Con suficientes filas, aún tendrá problemas con un desplazamiento lo suficientemente grande.

Tratar de almacenar y mantener la posición precisa de las filas también será un enfoque costoso (esto lo sugiere, por ejemplo, benjist). Si bien es técnicamente factible, adolece de limitaciones similares a las que se derivan del uso de MPTT con una estructura de árbol:obtendrá una ganancia significativa en las lecturas, pero terminará con tiempos de escritura excesivos cuando se inserte, actualice o elimine un nodo de tal manera que gran parte de los datos deban actualizarse al mismo tiempo.

Como es de esperar que quede más claro, no existe una bala mágica real cuando se trata de compensaciones tan grandes. A menudo es mejor buscar enfoques alternativos.

Si está paginando en función de la identificación (o un campo de fecha, o cualquier otro conjunto de campos indexables), un truco potencial (usado por blogspot, por ejemplo) sería hacer que su consulta comience en un punto arbitrario en el índice.

Dicho de otra manera, en lugar de:

example.com?page_number=[huge]

Haz algo como:

example.com?page_following=[huge]

De esa manera, mantiene un registro de dónde se encuentra en su índice y la consulta se vuelve muy rápida porque puede dirigirse directamente al punto de inicio correcto sin tener que pasar por miles de filas:

select * from foo where ID > [huge] order by ID limit 100

Naturalmente, pierde la capacidad de saltar a, p. página 3000. Pero reflexione un poco sobre esto:¿cuándo fue la última vez que saltó a un número de página enorme en un sitio en lugar de ir directamente a sus archivos mensuales o usar su cuadro de búsqueda?

Si está paginando pero quiere mantener la página desplazada de alguna manera, otro enfoque es prohibir el uso de un número de página más grande. No es una tontería:es lo que Google está haciendo con los resultados de búsqueda. Cuando ejecuta una consulta de búsqueda, Google le da un número estimado de resultados (puede obtener un número razonable usando explain ), y luego le permitirá explorar los primeros miles de resultados, nada más. Entre otras cosas, lo hacen por motivos de rendimiento, precisamente por el que te estás topando.