Page 1 sur 1

temps de chargement des données

Posté : 10 févr. 2006, 18:54
par Axel
Salut,

J'essaie de faire un fichier type csv avec les données de différentes tables. Une de mes tables contient environ 11 000 enregistrements, mais je n'en selectionne que 1000.
Lorsque je fais ma requête il faut compter environ 1 min 15 pour voir le resultat.
J'applique la meme requete sous phpmyadmin, il met à peu prés..... 10 sec. :oops:
Voici mon code:
if ( !isset($_GET['date']) ) { $_GET['date'] = "2006-01-01 00:00:00"; }
else { $_GET['date'] = urldecode($_GET['date']); }
$listeTables = array( "article","cat3","cat2","cat1","client", "marques" );//
$nbtot_resultat =0;
$csv ="";
foreach ( $listeTables as $value ) {
	$query_resultat="SELECT * FROM `".$value."` WHERE date_modif >= '".$_GET['date']."' ; ";//EXPLAIN
  $r_resultat = @mysql_unbuffered_query($query_resultat, $bdd_smd) or (die(mysql_error));
  $nb_chp = @mysql_num_fields($r_resultat);
  while ( $resultat= @mysql_fetch_array($r_resultat, MYSQL_NUM ) ) {
      for ($j=0; $j < $nb_chp ; $j++ ) {
        $csv .= "\"".$resultat[$j]."\";";
      }
      $csv = substr($csv, 0, -1)."\n";
  }
  @mysql_free_result($r_resultat);
}
echo $csv;
J'ai regardé le code dans myadmin, mais je n'ai rien vu de transcendental.
j'ai bien mis des index sur les champs utiles de ma table (quand je fais un explain le nombre de ligne analysé passe de 11 000 à 1 000).
et je ne vois aucune différence, le temps est exactement le meme.
Quelqu'un aurait-il une idée brillante qui illuminerait mon cerveau complètement assombri par cette histoire.
merci.

Re: temps de chargement des données

Posté : 10 févr. 2006, 19:31
par Hubert Roksor
la meme requete sous phpmyadmin, il met à peu prés..... 10 sec
C'est parce que phpMyAdmin n'affiche que les X premiers enregistrements alors que mysql_query() les récupère tous, peu importe ce que tu en feras par la suite.

Dès que j'ai 5 min je jette un œil sur ta requête, parce qu'aucune requête sensée ne devrait prendre plus d'une minute pour se résoudre.

Edit: je viens de lire que tu utilisais mysql_unbuffered_query(), du coup je retire presque tout ce que j'ai dit. Essaie quand même avec mysql_query() si tu ne l'as pas déjà fait.

Edit2: mmh, poste un EXPLAIN de toutes les requêtes, ça peut aider aussi

Edit3: as-tu essayé de remplacer ton code par un "SELECT ... INTO OUTFILE" ?

Posté : 10 févr. 2006, 19:45
par Axel
Voici pour les EXPLAIN

Code : Tout sélectionner

1 SIMPLE article range date_modif date_modif 8 1046 Using where 1 SIMPLE cat3 range date_modif date_modif 8 2 Using where 1 SIMPLE cat2 range date_modif date_modif 8 2 Using where 1 SIMPLE cat1 range date_modif date_modif 8 2 Using where 1 SIMPLE client range date_modif date_modif 8 5 Using where 1 SIMPLE marques range date_modif date_modif 8 4 Using where

Et en effet j'avais déjà essayé le mysql_query(). Je suis passé à l'unbuffered en pensant que les choses allaient s'améliorer mais non

Je viens de regarder pour le INTO OUTFILE mais en fait ça ne m'interesse pas car je ne souhaite pas créer un fichier c'est pour faire une variable qui sera envoyée en POST et traitée ensuite.

Posté : 10 févr. 2006, 20:28
par Hubert Roksor
Si tu le peux (accès aux fichiers du serveur MySQL via PHP), je te conseille quand même d'essayer "SELECT ... INTO OUTFILE" et de récupérer le résultat avec file_get_contents().

Sinon, la façon la plus efficace de récupérer tes données au format CSV est de les formater par le serveur MySQL. Par exemple, si tu sais que la structure des champs de la table "article" est "int int varchar":

Code : Tout sélectionner

SELECT article_id || ',' || cat_id || ',"' || REPLACE(article_name, '"', '\\"') || '"' AS csv_row FROM article
Et là, le plus gros du travail sera effectué par MySQL bien plus rapidement qu'en PHP. Le résultat sera un unique champs représentant une ligne CSV. Selon le "sql_mode" de ton serveur il faudra remplacer les || par un CONCAT().

Code : Tout sélectionner

SELECT CONCAT(article_id, ',', cat_id, ',"', REPLACE(article_name, '"', '\\"'), '"') AS csv_row FROM article

Posté : 10 févr. 2006, 20:31
par Hubert Roksor
Au fait, si ton but ultime est d'envoyer ces données via POST, tu devrais peut-être te tourner vers un format comme le XML ou WDDX si tu contrôles les deux parties. Tu pourrais même envisager un bête serialize().

Posté : 10 févr. 2006, 20:40
par Axel
Ca que c'est une idée qu'elle trés bonne ( je parle du post précédent)
Je m'enfile une petite tarte au poireaux derriere le gosier
et j'essaye ça ensuite

en fait mon but ultime est de mettre à jour une base de donnée locale à partir du site sans passer par myadmin et le tout en auto.

pour le XML, je ne connais pas assez pour m'y mettre tout de suite. Mais je ne pense pas que le problème vienne du formatage des données.

Je te tiens au courant
merci

Posté : 10 févr. 2006, 20:58
par Axel
J'ai résolu le problème mais je ne sais pas exactement d'ou cela provient.
j'ai fait mes essais sur IE et pour rire j'ai fait un essai sur Mozilla ....... et là plus de problème , l'affichage se fait en instantanée.( enfin presque )

alors j'ai réduit la page minimum c'est à dire un body et le code en php et là tout fonctionne correctement.
C'est le code HTML qui bloque IE lorsque qu'il y a un grand texte à afficher sinon il fonctionne correctement. :?

Je mets le code complet pour info:
<?php
require_once('Connections/bdd_smd.php');
mysql_select_db($database_bdd_smd, $bdd_smd);
include("codephp/session.php");
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <meta name="generator" content=
    "HTML Tidy for Windows (vers 1 June 2005), see www.w3.org">
    <title>
      Sud Modèles Diffusion, Gestion des commandes
    </title>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
    <link rel="stylesheet" href="charte/style_admin.css" type="text/css">
<script language="JavaScript" src="codejava/fonct_aff.js" type=
"text/javascript">
</script>
  </head>
  <body>
    <table width="100%" border="0" cellpadding="0" cellspacing="0">
      <tr>
        <td height="93" valign="top">
          <?php include("codehtml/entete_site_ssbout.htm"); ?>
        </td>
      </tr>
      <tr>
        <!-- Cellule du contenu de la page -->
        <td valign="top"></td>
      </tr>
      <tr>
        <td width="50%">
          <h2>
            Données à transférer
          </h2><?php
          if ( !isset($_GET['date']) ) { $_GET['date'] = "2006-01-01 00:00:00"; }
          else { $_GET['date'] = urldecode($_GET['date']); }
          $listeTables = array( "article","cat3","cat2","cat1","client", "marques" );//
          $nbtot_resultat =0;
          $csv ="";
          foreach ( $listeTables as $value ) {
                  $query_resultat="SELECT * FROM `".$value."` WHERE date_modif >= '".$_GET['date']."' ; ";//EXPLAIN
            $r_resultat = @mysql_unbuffered_query($query_resultat, $bdd_smd) or (die(mysql_error));
            //echo "$query_resultat<br />";
            //$nb_val= mysql_num_rows($r_resultat);
            $nb_chp = @mysql_num_fields($r_resultat);
            while ( $resultat= @mysql_fetch_array($r_resultat, MYSQL_NUM ) ) {
                for ($j=0; $j < $nb_chp ; $j++ ) {
                  $csv .= "\"".$resultat[$j]."\";";
                }
                $csv = substr($csv, 0, -1)."\n";
            }
            @mysql_free_result($r_resultat);
          }
          echo $csv;
                ?>
        </td><?php include ('codehtml/pied_page_site.php'); ?>
      </tr>
    </table>
  </body>
</html>
Je m'excuse pour le dérangement, en plus j'ai vérifié, toutes mes balises sont fermées, mais le ralentissement provient de là et il me fout le blues. :oops:

Ces temps-ci IE me pompe le système et surtout beaucoup d'énergie pour rien. :twisted: :evil:
Quoiqu'il en soit merci pour ton attention Hubert Roksor

Posté : 10 févr. 2006, 21:05
par Hubert Roksor
je ne pense pas que le problème vienne du formatage des données
...et c'est partiellement vrai. J'ai été moi-même confronté à un problème similaire mais avec une table plus large et l'impossibilité d'utiliser les extensions MySQL. Ma théorie là-dessus est que le client MySQL passe un temps fou à créer un tableau avec beaucoup de champs au moment de faire "mysql_fetch_*". Ensuite, on passe encore du temps à faire des concaténation en PHP alors qu'en transférant la charge de travail vers le serveur SQL on économise une grande partie de cette procédure. C'est un des très très rares cas où il vaut mieux charger le serveur SQL que PHP.

Content que tu sois parvenu à une solution satisfaisante, même si je n'y suis pour rien ;)