IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

Optimisation résultat SQL -> tableau


Sujet :

Langage PHP

  1. #1
    Expert éminent Avatar de Mr N.
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    5 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 5 418
    Points : 6 449
    Points
    6 449
    Par défaut Optimisation résultat SQL -> tableau
    Salut les gens,

    J'ai un petit souci de perfs. J'ai un objet, qui me sert à parcourir un résultat de requête sql, il implémente ArrayAccess, Countable. Ainsi je peux faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    foreach ($dao->searchById(123) as $row) {
       echo $row['champ_1'];
    }
    Très bien. Ça marche nickel.


    Maintenant j'ai une requête sql un peu complexe qui me retourne un ensemble de tuples (tutu_id, toto_id). Sur un système en charge, j'ai 50000 tuples qui me sont retournés... J'ai besoin de tous ces tuples donc je ne peux faire de LIMIT pour réduire le nombre.

    Là où j'ai un bottleneck, c'est que je mets ce résultât de recherche dans un tableau:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $tablo = array();
    foreach ($dao->searchComplexeQuery() as $row) {
       $tablo[] = $row;
    }
    Ça ça me bouffe des ressources

    Comme j'ai un ArrayAccess, j'ai pensé faire directement un:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $tablo = $dao->searchComplexeQuery();
    Mais plus tard dans mon script je fais, entre autres, un array_map sur mon $tablo pour extraire soit un tableau (tutu_id_1, tutu_id_2, ...) soit un tableau (toto_id_1, toto_id_2, ...). Et array_map n'apprécie pas que je lui passe un ArrayAccess, il veut un array tout court

    Mon code actuel:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    $tablo = array();
    foreach ($dao->searchComplexeQuery() as $row) {
       $tablo[] = $row;
    }
    //...
    $tutus = array_map('extract_tutu', $tablo);
    $totos = array_map('extract_toto', $tablo);

    Questions:
    - Y a-t-il une interface à implémenter dans la SPL qui me permettrait de balancer un objet à array_map ?
    - Ou un toArray() qui me permettrait d'avoir un tableau nativement sans passer par une couche de foreach en PHP ?
    - Ou une autre façon d'écrire mon code ?

    Merci.

    PS: je suis en PHP 5.1.6 mais suis curieux de connaitre si il y a une solution miracle en 5.2 ou 5.3.

  2. #2
    Membre habitué
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    101
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 101
    Points : 144
    Points
    144
    Par défaut
    Bonjour,

    Ton problème n'est pas le foreach à mon avis, mais plutôt le memory limit qui est dépassé par le gros tableau qui en résulte.

    Je pense que ta classe DB implémente un itérateur autour d'un resultset, et non d'un "vrai" array.
    Ainsi les 50 000 lignes sont en fait dans un memory HEAP de la base de données et pas dans la mémoire utilisable par PHP.

    En revanche la bascule en "vrai" array fait passer le resultset dans l'espace mémoire PHP sous la forme d'un array, et là ça coince en mémoire ...

    Edit : Pour le coup si tu augmente ton memory limit et que tu es prêt à générer le tableau, je verrai le toArray comme une méthode dans ta classe rowset que tu fetch actuellement et qui encapsulerait le foreach.

  3. #3
    Expert éminent Avatar de Mr N.
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    5 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 5 418
    Points : 6 449
    Points
    6 449
    Par défaut
    Ainsi les 50 000 lignes sont en fait dans un memory HEAP de la base de données et pas dans la memoire utilisable par PHP.
    Oui, tout à fait.


    Par contre je n'ai pas de problème de mémoire, c'est plutôt le temps d'exécution qui me fait souci. J'ai passé le memory_limit à 1024M (!) et ça ne change rien au problème.

  4. #4
    Membre habitué
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    101
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 101
    Points : 144
    Points
    144
    Par défaut
    Effectivement pour la vitesse, augmenter le memory_limit n'aidera en rien.
    Mais tes rows doivent être maigrichonne si ça passait sans augmenter le memory limit natif qui est à 16M je pense en 5.1 par defaut !

  5. #5
    Expert éminent Avatar de Mr N.
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    5 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 5 418
    Points : 6 449
    Points
    6 449
    Par défaut


    J'ai trouvé comment améliorer le bousin !
    J'utilise GROUP_CONCAT dans ma requête sql.

    Ceci me permet d'obtenir en une seule ligne toutes mes informations dont j'ai besoin. Cependant je perds la correspondance entre les deux parties du tuple (mais je n'en ai pas besoin donc osef !)

    En gros:
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    SELECT tutu_id, toto_id FROM table;
     
    tutu_id  | toto_id
    ---------+--------
    1        | 34
    2        | 25
    3        | 37
    ... # 50000 lignes comme ça

    devient =>

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    SELECT GROUP_CONCAT(tutu_id), GROUP_CONCAT(toto_id) FROM table;
     
    tutu_id  | toto_id
    ---------+--------
    1,2,3,...| 34,25,37,...

    Je gagne entre 2 et 3 secondes de traitement... énorme !

    Heureux je suis

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Ranger résultat sql dans un tableau avec while
    Par lemano dans le forum Langage
    Réponses: 4
    Dernier message: 15/06/2010, 11h36
  2. [MySQL] sortie de résultats d'un ordre sql en tableau
    Par opeo dans le forum PHP & Base de données
    Réponses: 5
    Dernier message: 08/08/2008, 17h56
  3. Tableau avec résultat SQL d'une BDD Access
    Par Courgette17 dans le forum JDBC
    Réponses: 4
    Dernier message: 24/04/2007, 12h24
  4. [MySQL] Affichage de résultats SQL dans un tableau
    Par illight dans le forum PHP & Base de données
    Réponses: 8
    Dernier message: 14/02/2007, 10h24
  5. [Oracle] Tableau résultat Sql et casse
    Par cbroissa dans le forum PHP & Base de données
    Réponses: 9
    Dernier message: 13/04/2006, 00h44

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo