Paginacion

Es muy común en el desarrollo WEB que se tenga la necesidad de presentar por partes la información consultada a una base de datos, esto por cuestiones de presentación en la mayoria de los casos, para ello hay muchas opciones de solución ya sea a nivel de base de datos o de la aplicación. Por esto quisiera saber su opinión considerando sus conocimientos y experiencia respecto a la mejor opción en función del desempeño.

Considerando una consulta a una tabla que guarde mas de 1 millon de registros y que se requiera una consulta que devuelva varios miles de registros, cual seria la mejor opcion para la paginación???? (considerando en primer lugar el desempeño, es decir el tiempo que se tarde en mostrar la información)

a) Construir una sentencia SQL o SP con los parametros necesarios para que devuelva el número de registros y pagina requeridos.
b) Utilizar los metodos del ResultSet de JDBC (absolute(), relative(), etc) para implementar la paginación
c) Utilizar una de las implementaciones para la paginacion a nivel de presentacion (custom tags, etc)

Espero que den su opinión porque se abriria un debate interesante.

saludos

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de ezamudio

combinacion de todo

La ultima opción que mencionas no es nada eficiente a nivel de base de datos, pero es necesaria para presentar tus datos de manera que el usuario no tenga que ver una lista gigantesca de un solo golpe. La paginación en el caso concreto que mencionas debe empezar desde que vas obteniendo los datos.
iBatis por ejemplo te facilita obtener páginas de datos, con ciertas restricciones (creo que debe haber una llave única y obviamente debes tener un índice sobre dicha llave en la tabla). Además el query lo debes tener con algunos hints para que el servidor de base de datos solamente te devuelva los registros necesarios. Por ejemplo si quieres solamente 1000 registros en PostgreSQL pondrias hasta el final del query un "LIMIT 1000"; porque simplemente cortar el ResultSet cuando cuentas 1000 registros no es tan eficiente, dado que el servidor ya obtuvo todos los datos que cumplen con tu condicion (podrian ser varios miles) y te los esta devolviendo, lo que cortas ahi es para ya no obtener mas datos de tu lado pero el servidor ya tuvo que hacer el trabajo; si le envias al servidor la info de que solo quieres mil registros, obtendra solamente los primeros mil y eso te devolverá.
Así que creo que lo mejor es que hagas una combinación de todo lo que mencionas. Puedes obtener del servidor los datos suficientes para unas 4 o 5 paginas de presentación (por ejemplo 500 registros, si los presentas de 50 en 50, ya tienes 10 paginas). Eso te conviene tambien para que no tengas que estar enviando un query al DBMS por cada pagina que necesitas; obtienes un equilibrio en donde no estas generando un query por cada pagina (lo cual cargaria mucho el DBMS) y no obtienes todos los datos de golpe (lo cual saturaria tu app server).

Given the choice of dancing pigs and security, users will choose dancing pigs, every single time.
Steve Riley

Imagen de Gallosuarez

Posible solución ...

eli_fm:

Realice la siguiente solución en una base de datos Interbase/Firebird (no creo que haya problema hacerlo en cualquier otra base de datos [he visto que casi todas las bases de datos tienen métodos similares]). La he probado con mas de 100 mil registros y tarde en devolverme los resultados entre 70 - 90 mseg [milisegundos]).

Para que esto funcione tu sentencia SQL debería tener al menos tres parámetros:
pag_num (Número de página)
display_rows (Número registro a desplegar)
str_srch (palabra de búsqueda)

 

Para obtener el número total de páginas que tienes de acuerdo a tu búsqueda hay que ejecutar antes la siguiente sentencia:
 

Consideraciones: tengo indexado el campo donde se hace la búsqueda (SEARCH_FIELD). En versiones anteriores de la base de datos no era tan eficiente cuando utilizabas SELECT COUNT(*) FROM TABLE En versiones posteriores esto funciona de las mil maravillas.

Implementé la misma solución usando un procedimiento almacenado, pero lo que no me gustó es que para que la sentencia me regrese la cantidad total de páginas la única manera, hasta el momento, es con el resultado de la sentencia, lo cual repetía el valor :display_rows de veces.

Saludos,
Gerardo Suárez Trejo