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

PHP & Base de données Discussion :

Optimisation de scripts PHP/MySQL [Débat]


Sujet :

PHP & Base de données

  1. #161
    Membre à l'essai
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juillet 2005
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juillet 2005
    Messages : 12
    Points : 16
    Points
    16
    Par défaut
    Bonjour,

    Un autre petit test sur l'affichage de chaines de caractère avec variable et caractères spéciaux.
    Exécuté 30 000 fois chacun :

    métode 1 : <?php echo "une chaine de caractère avec $var dedans et caractère spéciaux : \n\n" ; ?>
    durée : 0.20288

    métode 2 : <?php echo 'une chaine de caractère avec '.$var.' dedans et caractère spéciaux : '."\n\n" ; ?>
    durée : 0.076507

    métode 3 : <?php echo 'une chaine de caractère avec ', $var, ' dedans et caractère spéciaux : ', "\n\n" ; ?>
    durée : 0.062021
    L'echo avec virgules est donc préférable quelque soit les paramêtres.

  2. #162
    Rédacteur

    Homme Profil pro
    Geek entrepreneur
    Inscrit en
    Novembre 2004
    Messages
    1 224
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Geek entrepreneur

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 224
    Points : 2 373
    Points
    2 373
    Par défaut
    Ce petit script permet de bencher un site. Il est conseillé de commencer par des petites itérations afin de ne pas boucler pendant des heures ^^

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
     
        // Inclusion des lib PEAR 
        // --------------------- 
        // récupération de l'os sur lequel on est
        // on en a besoin pour déterminer le séparateur utilisé dans le PATH
        if (strstr(PHP_OS, 'WIN') == FALSE) 
        {
        	$separateur = ':';
        } 
        else 
        { 
        	$separateur = ';';
        }
     
        // Inclusion des lib PEAR
        // ---------------------
        set_include_path(get_include_path() . $separateur . 'PEAR');
     
        // Le client pour les requêtes
        // ---------------------------
        require_once 'HTTP/Client.php'; 
     
        // Bench du site (classe PEAR)
        // ---------------------------
        require_once ('Timer.php');               
     
     
        // les liens normaux
        $tab_link = array ('http://localhost/localweb/test/index.php?page=news',
                           'http://localhost/localweb/test/index.php?page=tools',
                           'http://localhost/localweb/test/index.php?page=dossierindex',
                           'http://localhost/localweb/test/index.php?page=membres,
                           'http://localhost/localweb/test/index.php?page=autre);
     
     
        // Positionner le runtime assez haut pour ne pas être bloqué
        set_time_limit(0);    // six minute timeout
        ini_set("memory_limit","256M");
     
        // Début du bench
        // --------------
        $bench = new Benchmark_Timer(); 
        $bench->start();
     
        $client =& new HTTP_Client(); 
     
        $bench->start();
     
        $cpt=0;
        // Bench de chaque page
        foreach ($tab_link as $a_row )
        {
            $cpt++;
            $bench->setMarker('test:'.$cpt);
             for ($i=0;$i<10;$i++)
            {
                $res = $client->get ( $a_row );        
            }
            $bench->setMarker('test de ' . $a_row );
        }
     
        $bench->stop();        
        $bench->display();
    Il est possible d'en faire une fonction ou une classe, de rendre le nombre d'itérations paramétrables et de passer le tableau des liens a bencher en paramêtre.
    Ca permet de voir quelles sont les parties du site qui prennent le plus de temps et de garder des traces de ces perfs pour pouvoir les comparer plus tard après une modification par exemple.

  3. #163
    Membre habitué
    Homme Profil pro
    Directeur technique
    Inscrit en
    Mars 2005
    Messages
    251
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2005
    Messages : 251
    Points : 174
    Points
    174
    Par défaut
    Citation Envoyé par Squallynou
    Bonjour,

    Lorsque vous devez compter un nombre d'enregistrement d'une table compotant un champ 'id', et que cette table ne subit jamais d'effacement (table contenant chaque connection au site par exemple, pour faire un compteur avec stats sur le pays etc.) plutôt que de faire un Where 1 et compter le nombre de lignes retournées, faites un Where 1 order by id desc limit 0,1

    L'id retourné est le dernier et correspond au nombre d'enregistrement puisque dans ce genre de table aucun n'est supprimé. Donc un seul enregistrement retourné au lieu de tous.
    un select max serait peut etre plsu conseille, non ?

  4. #164
    Membre habitué
    Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    161
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2005
    Messages : 161
    Points : 185
    Points
    185
    Par défaut
    un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select count(*) from table
    c'est encore plus efficace (sur les tables myisam en tous cas)

  5. #165
    Membre habitué
    Homme Profil pro
    Directeur technique
    Inscrit en
    Mars 2005
    Messages
    251
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2005
    Messages : 251
    Points : 174
    Points
    174
    Par défaut
    oui, en cas d'un id manquant en plein milieu, c'est meme plus correct sinon c la meme chose voire moins en ressources mais je pinaille lol

  6. #166
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9
    Points : 8
    Points
    8
    Par défaut
    et SELECT MAX(id) FROM table ? ça va pas?

  7. #167
    Membre éprouvé

    Profil pro
    Inscrit en
    Mai 2005
    Messages
    657
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 657
    Points : 910
    Points
    910
    Par défaut
    Salut,
    Il me semble avoir lu que MyISAM stocke le nombre d'enregistrement, dans tout les cas pour obtenir le nombre d'enregistrements, "SELECT COUNT(*) FROM table" devrait être la solution la plus rapide.
    Toute la documentation Ruby on Rails : gotapi.com/rubyrails
    Mes articles :
    > HAML : langage de template pour Ruby on Rails

  8. #168
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    842
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 842
    Points : 696
    Points
    696
    Par défaut
    Petite remarque amusante. La fonction array_map est lente. Il est plus rapide d'utiliser un parcours avec foreach, que d'appliquer map. Apparement, il est également plus rapide de donner un nom de fonction en paramètre plutôt qu'une fonction lamda crée avec create_function. A vérifier ;) J'ai gagné 40 % rien qu'en remplaçant les fonctions map. Interessant pour une partie dont le temps d'execution se compte en secondes.

  9. #169
    Membre régulier
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    401
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 401
    Points : 120
    Points
    120
    Par défaut redimenssionement image
    Je souhaite afficher des images sur une page.
    Les images pèsent environs 100ko chacune, je souhaite en afficher environs 30 par page.
    Si j'utilise le la librairie GD2 pour redimenssioner, est ce que les images seront réduites coté serveur en étant mise dans le cache (qui, normalement réduirait le poid des images), ou alors c'est un redimenssionement coté client (style <IMG width="xx" height="xx">) ??

    Merci
    www.ou-dejeuner.com A chacun son déjeuner ! |Blackprism.org

  10. #170
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Août 2005
    Messages
    1
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 1
    Points : 1
    Points
    1
    Par défaut
    Bonjour,

    j'ai une table auteurs avec des attributs comme le nom, le prénom, le sexe...
    Chaque auteur est lié à plusieurs articles dans une table articles (1 article = 1 enregistrement).
    je veux ressortir tous les articles d'un auteur donné ainsi que son nom, son prénom...

    Du point de vue de l'optimisation vaut-il mieux faire deux requêtes (et occuper du temps processeur) ou bien faire une jointure, quitte à avoir dans la table du résultat les attributs de l'auteur répétés pour chaque article (et donc occuper de la mémoire) ?

    Sachant que pour l'exemple j'ai simplifié à l'extrême et que c'est beaucoup plus lourd en réalité (4 tables, entre 5 et 10 colones pour chaque table et jusqu'à plus d'une centaine d'enregistrements à ressortir).

    j'éspère être clair (il est tard)

    Merci d'avance.

  11. #171
    Membre éclairé
    Avatar de genova
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    487
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 487
    Points : 790
    Points
    790
    Par défaut
    Pour ce type de configuration il faut faire une jointure, c'est justement fait pour ça
    Testez le forum Fire Soft Board, un forum libre, gratuit et français.

    Système de template de phpBB - Lisez la FAQ PHP avant toute question si vous débuttez en PHP.

  12. #172
    Futur Membre du Club
    Profil pro
    Inscrit en
    Août 2005
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 7
    Points : 6
    Points
    6
    Par défaut
    Je pense qu'on devrait refaire ce sujet... là on a un paquet de posts, donc certains inutiles... j'ai pas eu le courage de tout lire...

    je vais donc peut être redire des choses déja indiquées, mais voila mes habitudes en matière d'optimisation



    Portabilité
    - toujours utiliser la balise <?php au lieu du simple <?
    - inclure des conditions pour détecter si certaines fonctions (tels que les magic_quotes) sont actives, et faire un addslashes ou non en conséquence

    Économie de ressources
    - bannir le "SELECT *" de ses scripts... même si on prend la totalité des champs, les nommer un par un, ce qui permet de s'y retrouver plus facilement par la suite, mais surtout d'économiser les ressources dans le cas où un nouveau champ (et inutilisé sur la page) serait rajouté

    Rapidité d'exécution
    - utiliser les simples quotes avec du texte, et toujours concaténer lorsqu'il y a une variable
    - pour la concaténation, utiliser les virgules à la place des points (ne fonctionne que avec echo, et pas avec print, ni pour les concaténations entre variables... et il ne faut pas entourer le texte de parenthèses)
    - éviter les for... les while avec une indentation a l'intérieur sont sensiblement plus rapides
    - éviter l'opérateur ternaire ou les switch... préférez un "if" qui n'est pas forcément plus difficile a comprendre, et qui est sensiblement plus rapide
    - si vous voulez rajouter quelque chose a la suite d'une variables, utilisez la syntaxe "$variable .= 'bonjour';" au lieu de "$variable = $variable . 'bonjour';", et même chose pour les indentations : "+=" ou "-="
    - éviter les regex... très lourdes... dans la mesure du possible, utilisez un str_replace au lieu d'un preg_replace, et ainsi de suite !

    Facilité de relecture
    - INDENTER !!!
    - donner des noms explicites aux variables
    - comme dit plus haut, ne pas utiliser un "SELECT *"
    - mettre des commentaires, et préciser au début du fichier sous quelle configuration il a été testé (register globals ? short tags ? magic quotes ? version de php ? version de mysql ?)

    Bons réflexes
    - faire des benchmarks au niveau de la rapidité d'exécution si vous avez un doute
    - si vous avez une tâche longue a faire, demandez vous si créer une interface (plus ou moins automatisée) ne vous faciliterait pas la vie

  13. #173
    Expert éminent
    Avatar de sekaijin
    Homme Profil pro
    Urbaniste
    Inscrit en
    Juillet 2004
    Messages
    4 205
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Urbaniste
    Secteur : Santé

    Informations forums :
    Inscription : Juillet 2004
    Messages : 4 205
    Points : 9 127
    Points
    9 127
    Par défaut
    Citation Envoyé par iubito
    Citation Envoyé par _Gabriel_
    salut,

    - les calculs répétés dans les boucles du style

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for($i=0;$i<sizeof($arr);$i++)
    ca c'est pas bon!!!
    peux-tu préciser un peu, je capte pas là...
    en fait en théorie tous les arguments du for son évalué à chage passage de la boucle.
    si sizeof ($arr) vaut 10 tu vas passer 10 fois dan sla boucle est tu vas 10 fois évaluer $i<sizeof($arr) tu vas donc appeler 10 fois la fonction

    alors que si tu calcule la valeur avant sizeofarr = sizeof($arr) tu ne teste que $i<$sizeofarr 10 fois mais tu n'appelle la fonction qu'une fois.

    je ne sais pas ce qu'il en est du moteur zend de php mais certain compilateur savent optimiser ce genre de chose et n'appelle la fonction qu'une fois.

    de façon générale pas de fonction dans l'argument d'une boucle.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    while (mafonction()) {
    ....}
    est l'équivalent (ce qui est exécuté) que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    $continuer = mafonction();
    while ($continuer) {
      ...
      $continuer = mafonction();
    }
    idem pour toutes les formes de boucles.
    la deuxième forme montre bien que mafonctio est appelé autant de fosi qu'elle retournera vrai + une.
    on vois bien qu'elle est dans la boucle.
    A+JYT

  14. #174
    Membre éclairé
    Avatar de genova
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    487
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 487
    Points : 790
    Points
    790
    Par défaut
    Il faudrait testern j'ai déjà eu des cas en C ou le code mettait quelques secondes de plus car je mettais justement un strlen() dans la condition.

    cependant ne pas oublier que PHP est un langage interpréte, il y a de très forts chances que le résultat soit mis en cache et non recalculé à chaque fois, en tout cas si j'avais programmé PHP c'est comme ca que j'aurais fait donc les développeurs ont surement eu cette idée.
    Testez le forum Fire Soft Board, un forum libre, gratuit et français.

    Système de template de phpBB - Lisez la FAQ PHP avant toute question si vous débuttez en PHP.

  15. #175
    Expert éminent
    Avatar de sekaijin
    Homme Profil pro
    Urbaniste
    Inscrit en
    Juillet 2004
    Messages
    4 205
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Urbaniste
    Secteur : Santé

    Informations forums :
    Inscription : Juillet 2004
    Messages : 4 205
    Points : 9 127
    Points
    9 127
    Par défaut
    c'est plus compliqué que mettre en cache il faut s'assurer que dans le corps de la boucle les arguments de la fonction appelé dans le test ne change pas.

    il faut aussi s'assurer qu'il n'y a pas d'effet de bord. la fonction appelé dans la condition utilise peut être des paramètres globaux qui pourraient changer de valeur dans le corps.

    bref il faut assurer l'indépendence du résultat de la fonction dans la contion de l'algo du corp.

    ce genre d'analyse est particulièrment difficile à faire. et je ne suis pas du tout sur que php sache le faire.

    plus probablement il est possible que le moteur zend pour un certain nombre de fonctions prédéfinie sache s'assurer de l'indépendance et donc mettre en cache.
    si c'est le cas c'est dans des cas très particulier.

    A+JYT

  16. #176
    Membre éclairé
    Avatar de genova
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    487
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 487
    Points : 790
    Points
    790
    Par défaut
    Oui en fait tu as probablement raison. Les variables PHP sont probablement dans une listes chainées, et je me disais qu'il sufirait peut être simplement de définir un flag dans cette structure, qu'on met à TRUE dès que la variable recoit une modification. Si la variable n'est pas modifiée dans la boucle le flag reste à FALSE, et le for () par exemple n'a pas besoin de recalculer cette variable. C'est un peu idéaliste mais c'est surement faisable, mais comme tu le dit je doute PHP finalement l'ai fait, il y a beaucoup de paramètres à prendre en compte
    Testez le forum Fire Soft Board, un forum libre, gratuit et français.

    Système de template de phpBB - Lisez la FAQ PHP avant toute question si vous débuttez en PHP.

  17. #177
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    60
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 60
    Points : 81
    Points
    81
    Par défaut
    Bon topic,

    juste un point à propos de MySQL et PHP : les moteurs de base de donnée sont fait pour structurer/organiser/formater les données. Donc ils sont optimisés pour ça, et le font plus vite que PHP.
    Comme cela a déjà été dit, mieux vaut utiliser SQL plutôt que PHP pour ces tâches, et quelques fonctionnalitées 'avancées' de SQL peuvent être fort utiles :

    *les jointures
    *les requêtes imbriquées (à partir de MySQL 4.1, et pour certaines formes 4.0) : remplace plusieurs requêtes à la suite par 1 seule
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    SELECT champs1, champs2, etc...  FROM table WHERE id =
       (SELECT id FROM autre_table WHERE...) ;
    *les transactions (ça c'est plutôt pour la sécurité), mais faire un commit après ses requêtes c'est toujours mieux
    *pour les problèmes de base de données bloquée par un script : les locks (verrous), mettre un lock en lecture/ecriture sur une ligne plutôt que sur la table entière

    Pour un script qui utilise intensément les bdd, je pense que c'est sur les connexions qu'il faut se concentrer : ça peut gagner beaucoup de temps.

    Le mode de connexion peut aussi jouer un rôle : si la base de donnée est locale (sur le même serveur PHP), on peut se connecter avec un socket plutôt qu'en TCP, je crois que c'est plus rapide.

    Voilà, si quelqu'un veut bien compléter/corriger ce que j'ai écrit ...

    --
    Rom_1

  18. #178
    Membre éclairé
    Avatar de genova
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    487
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 487
    Points : 790
    Points
    790
    Par défaut
    Les bases de données sont effectivement faites pour formater les données, néanmoins un cache PHP avec un tableau à inclure évitera de :
    1) Faire une requète vers le serveur SQL (ce qui peut être important dans certains cas)
    2) Avoir les données directement dans le tableau sans se taper un déplacement de pointeur ligne par ligne avec un truc genre mysql_fetch_array()
    Testez le forum Fire Soft Board, un forum libre, gratuit et français.

    Système de template de phpBB - Lisez la FAQ PHP avant toute question si vous débuttez en PHP.

  19. #179
    FFF
    FFF est déconnecté
    Membre actif Avatar de FFF
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    342
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 342
    Points : 282
    Points
    282
    Par défaut
    je viens de surfer sur ce thread en étant sûr de trouver ce que je vais annoncer. Et non !!!! Grande surprise (ah moins que ma fonction de recherche de IE me joue des tours, dans ce cas là DSL) je n'ai pas trouvé l'une des plus grandes optimisations concernant les bases de données :



    Prévu spécialement pour des sites web comme developpez.com avec bcp de forums de users de postes donc de bases de données.

    Indispensable en tous les cas !

  20. #180
    Expert confirmé
    Avatar de siddh
    Inscrit en
    Novembre 2005
    Messages
    3 868
    Détails du profil
    Informations personnelles :
    Âge : 47

    Informations forums :
    Inscription : Novembre 2005
    Messages : 3 868
    Points : 5 011
    Points
    5 011
    Par défaut
    c'est effectivement un plus mais ca peut avoir des inconvenients, si tu as droit a 20 connections simultanées et que tu fais du pconnect, tu seras limité a 20 users sur ton site alors que sans le pconnect, tu pourras en avoir plus car ils interrogeront pas tous la base en meme temps
    Alunissage : Procédé technique consistant à déposer des imbéciles sur un rêve enfantin.

    Cours | FAQ | Sources Javascript
    Cours | FAQ | Sources PHP
    Mes Articles

Discussions similaires

  1. [Débutant] Accélérer et optimiser ses scripts PHP
    Par Metallic-84s dans le forum Langage
    Réponses: 6
    Dernier message: 24/03/2006, 12h37
  2. [MySQL] [SGBD] Script PHP/MYSQL d'access FTP
    Par ChRom dans le forum PHP & Base de données
    Réponses: 1
    Dernier message: 09/01/2006, 01h52
  3. Réponses: 9
    Dernier message: 05/01/2006, 12h24
  4. Recherche Login Script PHP & MySQL
    Par whbh dans le forum SQL Procédural
    Réponses: 9
    Dernier message: 01/12/2005, 16h45
  5. [MySQL] [Script]Optimisation de scripts Php/MySQL (2)
    Par copy dans le forum PHP & Base de données
    Réponses: 8
    Dernier message: 27/08/2004, 08h33

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