Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
3132 connectés 

  FORUM HardWare.fr
  Programmation
  SQL/NoSQL

  [MySQL] optimisation (2 requêtes en une...) [4.0.12 final sortie]

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[MySQL] optimisation (2 requêtes en une...) [4.0.12 final sortie]

n°335944
ZeBorG
Yes we can!
Posté le 17-03-2003 à 23:07:19  profilanswer
 

Je suis en train de développer un moteur de recherche en PHP/MySQL.
Lors de l'affichage du résultat, j'affiche les 10 (ou 25 ou 50..) premier résultats ainsi que le nombre total de résultats.
 
Pour faire ceci, je fais dans un premier temps un :
SELECT COUNT(DISTINCT id) FROM ... WHERE ...
Pour connaître le nombre total de résultats puis un :
SELECT toto, tata, titi, ... FROM ... WHERE ... LIMIT 0, 10
Pour récupérer les 10 premier résultats pour les afficher.
 
Y a-t-il une meilleure manière de procéder que de faire ces 2 requêtes séparées ?
Je me demande s'il ne vaut mieux pas faire un :
SELECT toto, tata, titi, ... FROM ... WHERE XXX  
(sans limite donc)
De cette manière j'ai également le nombre total de résultat (mysql_num_rows()) mais je manipule un énorme array... En effet, ma base contient plusieurs centaines de milliers d'entrées...
 
Des idées ?


Message édité par ZeBorG le 19-03-2003 à 01:19:38
mood
Publicité
Posté le 17-03-2003 à 23:07:19  profilanswer
 

n°335958
ZeBorG
Yes we can!
Posté le 17-03-2003 à 23:33:14  profilanswer
 

Je viens de testé avec la solution à 1 requête et effectivement, ça va plus vite.
Au lieu de fair une boucle sur ma deuxième requête comme ceci :
 
while ($row=mysql_fetch_row($query_result_handle)){
 echo $row[0], $row[1], ...
}
 
je fait ça :
 
mysql_data_seek ($query_result_handle, ($page - 1) * $nb_rows);
 
while ($nb_rows-- && $row=mysql_fetch_row($query_result_handle)){
 echo $row[0], $row[1], ...
}
 
mais est-ce-que l'utilisation mémoire va beaucoup augmenter ?


Message édité par ZeBorG le 17-03-2003 à 23:34:00
n°336229
Spir
Words are timeless
Posté le 18-03-2003 à 12:11:38  profilanswer
 

Je suis moi aussi confronter au même problème.
Pour ma part j'avais opter pour la deuxième solution.

Citation :

mysql_data_seek ($query_result_handle, ($page - 1) * $nb_rows);  
 
while ($nb_rows-- && $row=mysql_fetch_row($query_result_handle)){  
echo $row[0], $row[1], ...  
}


Pour ce qui est de la question de l'utilisation de la mémoire, je pense que oui elle va augmenter. Mais je ne sais pas dans quel sens...

n°336304
Core 666
Posté le 18-03-2003 à 13:32:19  profilanswer
 

ZeBorG a écrit :

Je suis en train de développer un moteur de recherche en PHP/MySQL.
Lors de l'affichage du résultat, j'affiche les 10 (ou 25 ou 50..) premier résultats ainsi que le nombre total de résultats.
 
Pour faire ceci, je fais dans un premier temps un :
SELECT COUNT(DISTINCT id) FROM ... WHERE ...
Pour connaître le nombre total de résultats puis un :
SELECT toto, tata, titi, ... FROM ... WHERE ... LIMIT 0, 10
Pour récupérer les 10 premier résultats pour les afficher.
 
Y a-t-il une meilleure manière de procéder que de faire ces 2 requêtes séparées ?
Je me demande s'il ne vaut mieux pas faire un :
SELECT toto, tata, titi, ... FROM ... WHERE XXX  
(sans limite donc)
De cette manière j'ai également le nombre total de résultat (mysql_num_rows()) mais je manipule un énorme array... En effet, ma base contient plusieurs centaines de milliers d'entrées...
 
Des idées ?


C'est une question intéressante :jap:
 
Je pense pas qu'on puisse donner de réponse générale, ca dépend des scripts, et du facteur le plus limitant sur ta machine (processeur ou RAM). Vu que le LIMIT BY ne fait au final qu'éviter un traitement supplémentaire post-requête par le script, dans la mesure où l'intégralité des lignes qui valident ta clause WHERE est parcourue (que ce soit au niveau des datas ou des index, peu importe), je pense qu'il est dommage de faire une deuxième requête qui va grosso-modo être traitée de la même manière par MySQL.  
 
Il vaut peut être mieux récupérer toutes les données. En détruisant l'array dès qu'il n'est plus utilisé ca doit pas consommer grand chose comme mémoire. Tout dépend des scripts après bien sur mais bon.
 
L'idéal serait évidement qu'il y ait une fonction peu documentée qui permette d'obtenir le nombre de lignes qui auraient été retournées par ta requête si tu n'avais pas mis de LIMIT, en plus du mysql_num_rows, mais on peut toujours rêver :D
 
Ce serait à proposer au staff de MySQL AB, car c'est quelque chose qui servirait pas mal.


Message édité par Core 666 le 18-03-2003 à 17:20:16
n°336392
Spir
Words are timeless
Posté le 18-03-2003 à 14:33:34  profilanswer
 

En gros d'après ce que tu dis Core 666, il faudrait faire du PHP objet...

n°336440
Core 666
Posté le 18-03-2003 à 16:02:01  profilanswer
 

Ah quoi tu penses plus précisement ? Je suis pas certain de voir de quelle manière le PHP objet peut apporter un gain de perfs à ce niveau ?

n°336504
Spir
Words are timeless
Posté le 18-03-2003 à 17:18:00  profilanswer
 

Je ne sais pas exactement, je ne me suis pas très approfondie dans le PHP objet, mais je me demande si par ce moyen, on peut optimiser la chose.
Ce n'était qu'une question. Une idée, c'est à voir.
 [:spir]

n°336529
ZeBorG
Yes we can!
Posté le 18-03-2003 à 17:42:03  profilanswer
 

J'ai pu tester ma 2nd solution sur une machine moins performante que la mienne et voici les résultats :
 
Apparament, pour les recherches qui n'ont pas beaucoup de résultats, la 2nd solution est près de 2x plus rapide.
 
Par contre, si la recherche ratisse large et renvoie beaucoup de réponses, la recherche est plus longue et la machine moins puissante me dit qu'il y a moins de réponse qu'elle ne devrait !
Apparemens, la limitation en perf font qu'elle n'arrive pas à gérer une séléction aussi grande (~65000 entrées).
 
Je suis donc obligé de repassé à la solution à 2 requêtes à moins que qq trouve une autre solution ?
 
[EDIT] En fait sur ma machine moins puissante, la base n'a apparemment pas était mis à jours intégralement d'où le nombre moindre de résultats :whistle:  
Par contre, la 2nd solution prend quand même plus longtemps quant il y a beaucoup de résultats.


Message édité par ZeBorG le 19-03-2003 à 16:48:51
n°336535
Core 666
Posté le 18-03-2003 à 17:47:39  profilanswer
 

ZeBorG a écrit :

J'ai pu tester ma  
Par contre, si la recherche ratisse large et renvoie beaucoup de réponses, la recherche est plus longue


Ce n'est pas normal. Tu as moyen de vérifier si c'est la requête qui est plus longue ou si c'est le traitement en PHP ? Avec un show processlist en shell par exemple ?

n°336811
ZeBorG
Yes we can!
Posté le 19-03-2003 à 01:17:54  profilanswer
 

Core 666 a écrit :


Ce n'est pas normal. Tu as moyen de vérifier si c'est la requête qui est plus longue ou si c'est le traitement en PHP ? Avec un show processlist en shell par exemple ?

Non, ce n'est pas le traitement PHP.
Je manipule une BD relativement grande (plusieurs centaines de milliers d'entrées...)
 
De toute façon mon problème est résolut avec MySQL 4.0.12 qui viens juste d'être affiché comme étant "Production-Ready" (= ce n'est plus une bêta)
 
Si tu lis là :
http://www.mysql.com/doc/en/Nutshe [...] tures.html
Ils disent: "Functions like SQL_CALC_FOUND_ROWS and FOUND_ROWS() make it possible to know how many rows a query would have returned without a LIMIT clause."
Et tu sais ce que cela veut dire...

mood
Publicité
Posté le 19-03-2003 à 01:17:54  profilanswer
 

n°336813
ZeBorG
Yes we can!
Posté le 19-03-2003 à 01:35:33  profilanswer
 

Pour utiliser cette nouvelle fonctionnalité (uniquement dans 4.x) il faut procéder comme ceci :
 
$sql = "SELECT SQL_CALC_FOUND_ROWS * FROM table WHERE ... LIMIT 0, 50";
$result = mysql_query($sql);
 
$sql = "SELECT FOUND_ROWS()";
$count_result = mysql_query($sql);
 
De cette manière, MySQL n'effectue qu'une fois la requête. Le second mysql_query() ne fait que récupérer une valeur calculé précédemment.

n°337380
ZeBorG
Yes we can!
Posté le 19-03-2003 à 17:14:19  profilanswer
 

En fait, pour mon problème bizarre où j'obtenais moins de résultats avec la 2nd solution, c'est par ce que la base sur le vieille machine n'était pas à jours :whistle:  
Par contre la 2nd solution est quand même plus lente quant il y a beaucoup de résultats.
 
De toute façon mon problème est résolu avec mySQL 4.
 
Et pour être compatible mySQL 3.x je procède de la manière suivante :

Code :
  1. mysql_connect(HOST, USERNAME, PASSWORD) or die(mysql_error());
  2. @mysql_select_db(DATABASE) or die('Unable to select database');
  3. $mysql_version = mysql_result(mysql_query('SELECT VERSION()'), 0);
  4. if ($mysql_version[0]>= 4)
  5.    $sql_query = "SELECT SQL_CALC_FOUND_ROWS (...)" . $sql_from_query . $sql_where_query;
  6. else {
  7.    $sql_query_count = "SELECT COUNT(DISTINCT table.id)" . $sql_from_query . $sql_where_query;
  8.    $sql_query = "SELECT (...)" . $sql_from_query . $sql_where_query;
  9. }
  10. $sql_query .= " LIMIT " . ($page - 1) * $nb_rows . ", " . $nb_rows;
  11. (...)
  12. if ($mysql_version[0]>= 4){
  13.    $query_result_handle = mysql_query($sql_query);
  14.    $nb_results = mysql_result(mysql_query('SELECT FOUND_ROWS()'), 0);
  15. }
  16. else{
  17.    $query_result_handle = mysql_query($sql_query_count);
  18.    $nb_results = mysql_result($query_result_handle, 0);
  19. }
  20. (...)
  21. if ($nb_results == 0) {
  22.    echo 'no results';
  23.    mysql_close();
  24.    include 'footer.php';
  25.    exit();
  26. }
  27. if ($mysql_version[0]< 4)
  28.    $query_result_handle = mysql_query($sql_query);
  29. (...)
  30. mysql_close();
  31. include 'footer.php';

Voila, en espérant que ça peu aider qq :wahoo:


Message édité par ZeBorG le 19-03-2003 à 17:18:20

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  SQL/NoSQL

  [MySQL] optimisation (2 requêtes en une...) [4.0.12 final sortie]

 

Sujets relatifs
MySQL à partir d'un prog en C??[PHP] mysql / php -> formats de dates
deux versions de MySQL sur la même machine[MySQL] demande de conseil pour forum [résolu...]
comment avoir juste le bon coté du auto_increment de mysql?Aidez une débutante à se connecter sur une BD MySql !!!!!! HELP
mysql_real_connect[PHP-MySQL] Existe-t il une fonction qui renvoie la date de ....
MySQL 4.0 ca doit etre bon !!! les parametres de eskue ???Question optimisation (forum)...
Plus de sujets relatifs à : [MySQL] optimisation (2 requêtes en une...) [4.0.12 final sortie]


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR