¿Cual es la mejor forma de realizar paginación?

Hola compañeros:

Me surge la siguiente duda, ¿existe un método "óptimo" o considerado de "buena practica" para realizar paginado? He visto que existen muchas soluciones, la duda surge, porque me imagino que el rendimiento de estos paginados, depende de la cantidad de datos a regresar, yo solamente he paginado registros de una cantidad que podria decirse, no es muy grande, he utilizado paginación con JQuery y DisplayTag, me imagino que estas soluciones no son eficientes cuando hablamos de millones de registros (no se, por ejemplo 5 millones o mas), también he observado (en código que me ha tocado mantener) que a nivel consulta sql realizan el paginado, esto es, que por medio de una consulta SQL toman el total de registros y van realizando consulta de registro en relación a un rango de paginado, de nueva cuenta, ignoro si es la mejor manera de realizarlo, si alguien pudiera dar su opinión en relación a su experiencia o si alguien se ha enfrentado con esta situación, me gustaría saber su punto de vista.

Gracias !!!

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 WinDoctor

Si hablamos de millones de

Si hablamos de millones de registros como ejemplificas, creo que la mejor paginación es la que puede hacerse en la misma base de datos. Al menos en Oracle, se puede realizar una paginación, siendo muy efectivo cuando hablas de millones porque no cargas en memoria esa información.

Imagen de alucard1

Gracias

Supongo que esa solución funciona cuando hablamos de conexiones JDBC directas, ¿como aplica cuando se usa un framework de tipo ORM? (No quiero un tutorial ni mucho menos, solo tengo curiosidad, en saber como se hace, a nivel conceptual)

Saludos

Re: ORM

 

¡Psst! Oye, @alucard1 ... ¿Te refieres a algo como esto?

some img

Imagen de alucard1

Algo asi !!!

Si, algo mas o menos asi !!! Internamente sabes como funciona? De hecho esa es mi curiosidad !!! ¿Que hace el Entity Manager? ¿Consulta el total de registros y realiza consulta por consulta, segun cambien los rangos? ¿Consulta el total y almacena resultados en cache o memoria? La pregunta del tema principal, nace de curiosidad, porque como, ya lo habia mencionado, he dado mantenimiento a varios sistemas y la mayoria lo hace desde el propio SQL (Son JDBC sin ningun framework)

Repito, solo es curiosidad de saber como es la mejor forma y como internamente se hacen este tipo de cosas !!

Gracias y saludos

Re: Internamente

 

Depende de la implementación de JPA (que es lo que se utiliza en ese slide). Si consigo algo de tiempo, pondré las consultas SQL que hace alguna implementación (Hibernate, por ejemplo).

Imagen de beto.bateria

Ejemplo JPA de paginacion desde la BD

Lo mejor es hacerlo desde la base de datos, el ejemplo es con postgress:

Esto es en la implementacion de una clase del dominio

@Entity
@Table(name="customers")
//@NamedQuery(name="Customer.findAll", query="SELECT c FROM Customer c")

@NamedQueries({
        @NamedQuery(name="Customer.findAll", query="SELECT c FROM Customer c"),
        @NamedQuery(name="Customer.findAllOrderId", query="SELECT c FROM Customer c ORDER BY c.customernumber"),
        @NamedQuery(name="Customer.findById", query="SELECT c FROM Customer c WHERE c.customernumber = :id ")
       
})

En el DAO

        @SuppressWarnings("unchecked")
        @Override
        public List<Customer> getOffsetCustomers(int offset){
                Query query = em.createNamedQuery("Customer.findAllOrderId");
                query.setMaxResults(10); // equivalent to LIMIT
                query.setFirstResult(offset); // equivalent to OFFSET
                return query.getResultList();
        }

Esto es la implementacion en el controller

        @RequestMapping("")
        public ModelAndView getCustomers(){
                ModelAndView mv = new ModelAndView();
                List<Customer> customers = this.customerDAO.getOffsetCustomers(0);
                mv.addObject("customers",customers);
                mv.addObject("offset",10);
                mv.setViewName("customers/list");
                return mv;
        }

Espero que te ayude,

Muchas gracias :)

Muchas gracias :)

Imagen de ezamudio

en el SELECT

Ya lo han mencionado en comentarios previos, lo repito porque es lo que creo que es la mejor opción:

Paginas en el mismo SELECT. Tienes que hacer dos consultas: Una con SELECT COUNT(*) para saber cuántos registros son, y si es que te interesa desplegar cuántas páginas hay, y otro que es el SELECT para la pura página, acotado con LIMIT y OFFSET, y siempre ordenando por alguna llave para que los resultados sean consistentes.

Por ejemplo si muestras páginas de 30 registros, entonces si SELECT COUNT(*) te da 5 millones de registros pues son 166667 páginas. El query siempre va a llevar LIMIT 30 y el OFFSET lo calculas con la página-1 multiplicada por 30, o sea OFFSET 0 para la primera página, OFFSET 30 para la segunda, etc.

Usa la paginacion siempre

Es comun encontrar codigo donde regresan mas de 1000 registros pero eso es de cada quien, ahora esta muy de moda utilizar API's REST y alli siempre debe hacer una paginacion.

Para hacer una paginación existen muchas formas.

La mas comoda y sencilla esta con los Spring data repositories, practicamente no haces nada.

https://www.petrikainulainen.net/programming/spring-framework/spring-dat...

La otra es con criteria

https://examples.javacodegeeks.com/enterprise-java/hibernate/pagination-...

Igual con el entity manager se puede hacer.

Basicamente el algoritmo es el siguiente(reparenlo si me equivoco):

* Se define la pagina,numero.

* Se define el tamaño.

* Se obtienen el numero total de registros.

* Se obtiene el numero de paginas que se obtienen con el tamaño de pagina especificado.

* Se hace la consulta en el numero de pagina y se agrega un resultado maximo que es el tamaño de la pagina.

Y como con toda esa información en una API REST se va arañando un poco el concepto de lo que es Spring HATEOAS, donde ademas de darte una API REST paginada, también se auto descubre, algo asi como un WSDL pero mas dinamico y en REST :P

https://blog.zenika.com/2012/06/15/hateoas-paging-with-spring-mvc-and-sp...

Una guia de estilo para API's REST donde se recomienda la paginacion
https://platzi.com/blog/como-crear-apis/

Hola, fijate que yo hago lo

Hola, fijate que yo hago lo que comentas, los 2 query, pero tengo un problema tengo 2 botones y caja de texto, en la caja de texto muestro la pagina en donde se encuentran.Primero lo que hago esto

Dividir el numero de registros entre lo que voy a mostrar algo a si.

total= CountTotal/limite;//// el CountTotal es lo que trae el query, el limite es lo que muestro en este caso solo 10, ahi nos da el numero de paginas, luego programa el boton para ir pasando entre paginas, el codigo es el seguiente

page= Integer.parseInt(jTextField1.getText()) ;///se obtiene los datos de la caja de texto y se pasa a la variable
page*=10; //se multiplica por 10
cargarRegistros(page); //se manda el metodo
page+=1;//se suma la pagina para colocarla en la caja de texto

todo esto funciona bien cuando lo hago desde el boton, pero si yo le pongo en la caja de texto que quiero el a la pagina 3 en vez de mostrarme esa pagina me manda a la 4, ya que en el query el limit empieza 0,10 que es la pagina 1, limit 10,10 que es la 2, limit 20,10 que es la 3, te comento esto con los botones funciona,.

Paginación de lista creada por 2 servicios api rest

Buenas noches ante todo, yo tengo que paginar una lista que se alimenta de 2 servicios api rest, tengo que consultar los 2 servicios y después mesclarlos en una solo lista , paginar y ordenar, lo que yo hecho es siempre traerme todos los reistros desde 0 hasta ((pageNumber - 1) * pageSize) + pageSize) ,para cada servicio, después mesclarlos y ordenarlos, pero tiene una desventaja que cuando el pageNumber aumenta se pone mas pesado la consulta, aluna solución o forma de desarrollar ese tipo de caso.
Gracias.
Saludos Darwin