Jump to content
Sign in to follow this  
criocere

Gestion de la pagination

Recommended Posts

Bonjour,

Je souhaiterais avoir votre avis sur la pagination. Dans ma boutique et pour gérer la pagination, je suis amené à appliquer deux fois la même requête, la première pour connaitre le nombre total d'élément (je récupère donc tout ce qui répond a mes WHERE clauses) et la seconde ou j'ajoute une clause LIMIT à la fin pour remonter que le sous-ensemble qui correspond à la page en cours. Sous-ensemble que j'avais déjà remonté la fois précedente. Bref tout çà est un peu stupide et non optimisé !

Quelle est la meilleure façon de gérer la pagination donc connaitre le nombre total d'articles et de remonter que les articles de la page en cours en un minimum de requête, soit une ?

Merci

Share this post


Link to post
Share on other sites

Salut,

A mon avis, si tu acceptes de faire deux requêtes, ta solution semble la bonne.

On va imaginer que tu ne vas faire qu'une requête. Le résultat de cette requête devra comporter tous les champs nécessaires à l'affichage de ta page. Une solution consisterait à rechercher tous les resultats (pas uniquement les 10 premiers) et ensuite calculer la taille du tableau que tu peux obtenir à partir de ta requête. Le problème de cette solution, c'est que tu vas prendre beaucoup plus d'informations que tu en as besoin pour au final ne pas les utiliser!!! Certes, tu fais une seule requête... mais quelle requête!!! ;)

Perso, je pense que la solution à deux requêtes est plus intéressante car plus claire et plus logique (et peut-être plus rapide). Ensuite, tu peux faire un test sous PHPMyAdmin en regardant le temps d'éxécution. Mais attention, ce qui peut être efficace pour une base de données peut être totalement inadaptée pour une autre.

A+

Share this post


Link to post
Share on other sites

Le fait de passer par deux requêtes n'est pas stupide, à condition de faire attention à ne sélectionner que les id dans la première requête, celle qui doit te retourner le nombre de résultats. Par exemple si tu dois paginer une base de données de bouquin, ta première requête compte le nombre de résultats totaux :

SELECT id_livre FROM livre WHERE ...

Et la deuxième te renvoie les données pour la page en cours uniquement :

SELECT id_livre, auteur, editeur, resume, nb_de_pages, etc... FROM livre WHERE ... LIMIT 10

J'utilise une autre solution : j'exécute la première requête avec uniquement tous les id sans LIMIT, puis je boucle le tableau reçu sur les 10 résultats de ma page, et c'est dans la boucle que j'exécute la requête de sélection des données nécessaires. On a donc cette fois 11 requêtes : une grosse pour les id, et 10 petites requêtes de sélection ultra rapides pour les sélections de donées. Ce n'est peut-être pas une solution adaptée à tous les projets, mais pour moi ça fonctionne plus rapidement que 2 requêtes comme décrit au début.

Share this post


Link to post
Share on other sites
Le fait de passer par deux requêtes n'est pas stupide, à condition de faire attention à ne sélectionner que les id dans la première requête, celle qui doit te retourner le nombre de résultats. Par exemple si tu dois paginer une base de données de bouquin, ta première requête compte le nombre de résultats totaux :

SELECT id_livre FROM livre WHERE ...

... ou d'utiliser la fonction SQL qui va bien

SELECT count(*)......

Share this post


Link to post
Share on other sites

Il vaudrait mieux utiliser la fonction FOUND_ROWS, qui permet de faire ressortir le nombre d'éléments qu'aurai donné la requête, sans clause LIMIT.

J'en ai donné une petite explication sur ce topic.

Share this post


Link to post
Share on other sites

Salut,

bon, bah pour le coup, la solution de captain_torche me parait plus intéressante que la mienne... je ne savais pas que cette fonction existait... très intéressant!!!

A+

Edited by Bourinho

Share this post


Link to post
Share on other sites

Super captain torche, je ne connaissais pas, effectivement c'est exactement mon besoin ce SQL_CALC_FOUND_ROWS :)

Share this post


Link to post
Share on other sites

Génial ! Merci Captain ! J'ai modifié toutes mes pages sur ton modèle, et ça fonctionne nikel ! C'est plus propre comme cela, mais je ne note pas d'amélioration flagrante au niveau de la vitesse d'exécution... à voir pendant les montées en charge ?

Share this post


Link to post
Share on other sites

Logiquement, ça devrait diviser grosso modo par deux la charge serveur, mais j'ai pas eu l'occasion de le mesurer quantitativement.

Share this post


Link to post
Share on other sites

Je pense que le moteur MySQL est obligé de faire quand même 2 requêtes, mais la façon que tu proposes doit être optimisée en interne.

Share this post


Link to post
Share on other sites

Quel est l'intérêt d'un FOUND_ROWS() ( fonction propriétaire ) par rapport à count(*) ( standard SQL ) ?

Quelqu'un a fait des tests de performance comparée entre ces 2 fonctions ?

Share this post


Link to post
Share on other sites

Je pense que l'intérêt réside dans le fait qu'on peut exécuter cette fonction a posteriori.

Cependant, si la requète a déjà été faite, pourquoi embêter mysql ? Un mysql_num_rows marchera très bien.

Share this post


Link to post
Share on other sites

Le mysql_num_rows te ressortira le nombre de lignes retournées par ta requête, avec la clause LIMIT.

Le FOUND_ROWS te retournera le nombre de lignes SANS la clause LIMIT.

Donc, effectivement, on effectue deux requêtes sur le serveur MySQL, mais en cas de requête assez gourmande (liaisons entre tables à n'en plus finir, par exemple), on évite de la relancer une seconde fois.

Share this post


Link to post
Share on other sites

On peut supposer que l'utilisation de mysql_num_rows dans la première requête fait que mySQL stocke de manière temporaire le nombre de ligne total qq part et donc que le found_rows soit juste un accès à cette valeur, donc très rapide. Il serait intéressant de faire un INSERT entre les deux pour voir aussi.... Mais bon c'est pas mon cas de figure.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×
×
  • Create New...