Too Cool for Internet Explorer

Paginado de datos

Hora y Fecha: Diciembre 8, 2006 @ 7:13 pm Autor: Moisés Maciá
Categorías:
1,090 views

Después del tsunami menéame de ayer (en un par de horas tuve el tráfico de casi un mes) vamos a retomar un poco la temática habitual hablando de varios trucos para paginar datos en MySQL.

¿Qué es el paginado?

El paginado de datos consiste en trocear una salida de datos muy larga en paquetes mas pequeños y digeribles para el usuario. Hay ejemplos de paginados en la inmensa mayoría de aplicaciones, especialmente en las de Internet. Por ejemplo:

Paginado de Google:

Paginado de Google

Paginado de Flickr:

Paginado en Flickr

Paginado de Digg:

Paginado en Digg

¿Por qué debo paginar?

  • Para el usuario es más sencillo ver 10 paquetes de 10 resultados que 100 de golpe.
  • Probablemente al usuario sólo le interesen los resultados más relevantes que son los que aparecen en la primera o segunda página.
  • Para la base de datos es más sencillo y rápido traer 10 resultados que 100.
  • Para el servidor HTTP es más sencillo y rápido servir 10 resultados que pesan 20Kb en lugar de 100 resultados que pesan 200Kb.

¿Cómo paginar datos?

Para paginar los datos necesitamos de antemano dos cosas: el tamaño de la pagina y el total de filas que tenemos de datos.

Contamos el total de filas:

  1.  
  2. SELECT COUNT(*) AS total FROM employees;
total
---------------
63

Mediante la instrucción SQL LIMIT n,m podemos trocear los datos de salida y mostrar la pagina que nos interese. LIMIT acepta dos parámetros: el primero es el offset de la pagina y el segundo la cantidad de filas que devuelve.

Devolvemos 10 resultados de la pagina 3:

  1.  
  2. SELECT id,name FROM employees LIMIT 3,10;
id      name
------------------------
13     Pepe
22     Manolo
34     Jose
...

Necesitamos el total de filas para calcular cuantos paquetes de datos (paginas) necesitamos. En este caso tenemos un total de 63 filas paginadas de 10 en 10. Veamos un script PHP muy simple que nos devuelve las paginas:

  1.  
  2. $pagging = 10;
  3. isset($_GET[‘page’]) ? $current = (int)$_GET[‘page’] : $current = 1;
  4.  
  5. $q = mysql_query("SELECT COUNT(*) FROM employees;");
  6. $row = mysql_fetch_assoc($q);
  7.  
  8. $total_pages = (int)ceil($row[‘total’]/$pagging);
  9.  
  10. //header pagging
  11. echo "Pagina $current de $total_pages ({$row['total']} resultados)nn";
  12.  
  13. //body pagging
  14. $q = msql_query("SELECT id,name FROM employees LIMIT {$current-1},$pagging;");
  15. while($row = mysql_fetch_assoc($q))
  16. {
  17.    echo vsprintf("%dt%sn", array($row[‘id’], $row[‘name’]));
  18. }
  19.  
  20. //footer pagging
  21. echo "«t";
  22. for($i=0;$i < $total_pages;$i++)
  23. {
  24.    if($i === ($current-1))
  25.       echo " [$i] ";
  26.    else
  27.       echo " $i ";
  28. }
  29. echo "t»";
Pagina  1 de 7 (63 resultados)

13     Pepe
22     Manolo
34     Jose
...

«   [1] 2 3 4 5 6 7   »

Consideraciones para MySQL

Para calcular el paginado debemos utilizar obligatoriamente dos consultas como mínimo, si las consultas son complejas podemos tener un problema de rendimiento importante pero existen maneras de atajar el camino. Si la base de datos que utilizamos es MySQL existe un hack para devolver el resultado paginado y el total de filas en un solo paso.

Seleccionamos la pagina que nos interesa:

  1.  
  2. SELECT SQL_CALC_FOUND_ROWS id,name FROM employees LIMIT 0,10;

Miramos cuantas filas tiene en total:

  1.  
  2. SELECT FOUND_ROWS();

Siguen siendo dos consultas pero a efectos prácticos rinde como “una y media”, en cualquier caso nunca será tan lento como hacerlo con las dos consultas anteriores.

SQL_CALC_FOUND_ROWS funciona a partir de la versión 4 de MySQL si no recuerdo mal.

Las instrucciones SQL_CALC_FOUND_ROWS y FOUND_ROWS() deben ir una detrás de otra, si hacemos consultas por en medio es muy probable que nos encontremos con resultados imprecisos.

Me consta que Oracle tiene una instrucción equivalente pero no sabría explicaros, no tengo suficiente experiencia con esa base de datos. PostgreSQL y SQLite si que sé seguro que no pueden hacer uso de este hack, al menos en sus versiones actuales.

Paginado deluxe en CakePHP

Los usuarios de CakePHP estamos de suerte, Andy Dawson escribió un helper que permite realizar paginados de cualquier tipo de datos con muy poco esfuerzo. Permite ordenar datos tabulados por columnas y el interfaz de control funciona completamente en AJAX (si el cliente lo permite o nosotros lo forzamos).

Encontrareis todo lo referente al paginado en Bakery.





« Anterior post: Lo que el código no hace en la vida real (y si hace en las películas) | Próximo post: Vivimos en un mundo mal formado »

3 Comentarios para “Paginado de datos”

programame.net
5 de Enero de 2007 a las 2:32 am    

Paginado de datos en PHP…

El paginado de datos consiste en trocear una salida de datos muy larga en paquetes mas pequeños y digeribles para el usuario. Hay ejemplos de paginados en la inmensa mayoría de aplicaciones, especialmente en las de Internet. Un articulo que explica c…

Yuri Morales
19 de Junio de 2007 a las 3:24 pm    

Excelente, muchas gracias por este tutorial era justo lo que estaba buscando. Me ha servido muchisimo. sigue adelante. !!!!

Gracias de Nuevo.

[...] tenga que utilizar el scroll para revisar los últimos resultados, debes implementar un sistema de paginado, el cuál le permita al usuario en una sola [...]


Bad Behavior has blocked 382 access attempts in the last 7 days.