criocere Posté 8 Juillet 2006 Posté 8 Juillet 2006 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
Bourinho Posté 9 Juillet 2006 Posté 9 Juillet 2006 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+
Kalt Posté 10 Juillet 2006 Posté 10 Juillet 2006 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.
Spidetra Posté 10 Juillet 2006 Posté 10 Juillet 2006 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(*)......
captain_torche Posté 10 Juillet 2006 Posté 10 Juillet 2006 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.
Bourinho Posté 10 Juillet 2006 Posté 10 Juillet 2006 (modifié) 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+ Modifié 10 Juillet 2006 par Bourinho
criocere Posté 10 Juillet 2006 Auteur Posté 10 Juillet 2006 Super captain torche, je ne connaissais pas, effectivement c'est exactement mon besoin ce SQL_CALC_FOUND_ROWS
Kalt Posté 10 Juillet 2006 Posté 10 Juillet 2006 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 ?
captain_torche Posté 10 Juillet 2006 Posté 10 Juillet 2006 Logiquement, ça devrait diviser grosso modo par deux la charge serveur, mais j'ai pas eu l'occasion de le mesurer quantitativement.
criocere Posté 10 Juillet 2006 Auteur Posté 10 Juillet 2006 En tout cas intellectuellement, c'est très satisfaisant
Kalt Posté 10 Juillet 2006 Posté 10 Juillet 2006 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.
Spidetra Posté 10 Juillet 2006 Posté 10 Juillet 2006 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 ?
MarvinLeRouge Posté 11 Juillet 2006 Posté 11 Juillet 2006 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.
captain_torche Posté 11 Juillet 2006 Posté 11 Juillet 2006 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.
criocere Posté 11 Juillet 2006 Auteur Posté 11 Juillet 2006 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.
Sujets conseillés
Veuillez vous connecter pour commenter
Vous pourrez laisser un commentaire après vous êtes connecté.
Connectez-vous maintenant