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 :

écriture en bdd extraordinairement lente [MySQL]


Sujet :

PHP & Base de données

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 493
    Billets dans le blog
    1
    Par défaut écriture en bdd extraordinairement lente
    Bonjour,

    j'ai un problème de lenteur de mon script, mentionné dans cette discussion https://www.developpez.net/forums/d2124326/php/langage/script-stoppe/ au post #10.

    Le SGBD est MySQL.

    Mon script d'accès à la bdd est le suivant :
    Code php : 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
     static public function  putInDBLicense($refrefTable, $ref_ppp){
            $save_success = true;
     
            /* pour ne pas avoir à modifier tout le code qui suit    */
            $ref_app = $refrefTable->getref_App();
            $ref_platform = $refrefTable->getref_Platform();
            $ref_country = $refrefTable->getref_Country();
            $ref_location = $refrefTable->getref_Location();
            $ref_company = $refrefTable->getref_Company();
            $ref_BU = $refrefTable->getref_BU();
            $ref_usermanager = $refrefTable->getref_Usermanager();
            $ref_US_user = $refrefTable->getref_US_user();
            $ref_USL_user_license = $refrefTable->getref_USL_user_license();
            $ref_Domain = $refrefTable->getref_Domain();
            $ref_Email = $refrefTable->getref_Email();
            $ref_license = $refrefTable->getref_License();
     
     //insert ou update pour ap_application
            /** @var \ticket_rawsrc\model\license\table\AP_application  $ref_app*/
     
            $save_success &= $ref_app->save(true, $ref_app->getAP_appli_name(), $id_platf, $ref_ppp);  //mise en bdd
     
    // 11 autres écritures en bdd (insert ON DUPLICATE KEY) avec parfois des SELECT avant

    Ce traitement d'écriture en bdd est effectué lors de la lecture d'un fichier CSV. Il est effectué à chaque ligne lue. Le fichier compte 110000 lignes. Au bout de 6 heures, 4500 lignes ont été traitées. Donc une règle de 3 indique que ça prendra 6 jours (6*110000/4500/24 =6,1)
    Comment puis-je optimiser ça ?

  2. #2
    Expert confirmé
    Avatar de Séb.
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    5 322
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 322
    Billets dans le blog
    17
    Par défaut
    C'est dur de te répondre, on ne sait pas ce qui se cache derrière toutes ces méthodes et ni à quoi ressemblent tes UPDATE/INSERT.

    Tu as posé des chronos un peu partout pour voir où ça ralentit ?

  3. #3
    Membre Expert
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 493
    Billets dans le blog
    1
    Par défaut
    Merci de me répondre. J'ai réalisé après coup qu'il manquait des informations.

    Je les donnerai plus tard car il y a un problème de mesure du temps. J'ai fait un essai plus simple : dans la méthode putInDBLicense, on met que les getters mais pas les écritures :
    Code php : 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
    static public function  putInDBLicense($refrefTable, $ref_ppp){
            $save_success = true;
     
            /* pour ne pas avoir à modifier tout le code qui suit    */
            /** @var \ticket_rawsrc\model\RefTableLicense  $refrefTable */
            $ref_app = $refrefTable->getref_App();
            $ref_platform = $refrefTable->getref_Platform();
            $ref_country = $refrefTable->getref_Country();
            $ref_location = $refrefTable->getref_Location();
            $ref_company = $refrefTable->getref_Company();
            $ref_BU = $refrefTable->getref_BU();
            $ref_usermanager = $refrefTable->getref_Usermanager();
            $ref_US_user = $refrefTable->getref_US_user();
            $ref_USL_user_license = $refrefTable->getref_USL_user_license();
            $ref_Domain = $refrefTable->getref_Domain();
            $ref_Email = $refrefTable->getref_Email();
            $ref_license = $refrefTable->getref_License();
     
     
        //insert ou update pour pl_platform
         /*   /** @var \ticket_rawsrc\model\license\table\PL_platform  $ref_platform
     
          /*  $save_success &= $ref_platform->save($ref_ppp)
          ... */
    rien que ça, c'est hyper long. Au lieu d'être quasi-instantané, les 110000 appels à la méthode, ça prend au moins 10 minutes.

    Citation Envoyé par Séb. Voir le message
    Tu as posé des chronos un peu partout pour voir où ça ralentit ?
    Honnêtement, je l'avais pas fait car retenu (par erreur) que c'était pas fiable ; en fait, j'ai confondu mesure de temps et mesure de consommation de mémoire, à cause de (du 03/12...)
    Citation Envoyé par CosmoKnacki Voir le message
    Les bizarreries que tu constates à propos de la mémoire sont dues à la manière dont PHP alloue de la mémoire pour les tableaux. Cette quantité allouée est toujours une puissance de 2.

    Prenons un exemple bidon (pour ce qui est des nombres): un tableau stocke des données qui nécessite 600 octets, PHP allouera donc 1024 (2 puissance 10) octets pour le tableau, ce qui en proportion représente une perte énorme. Pourquoi fait-il ça? Pour ne pas avoir à allouer de la mémoire toutes les 5 minutes, c'est un dilemme entre vitesse et mémoire nécessaire. Si le tableau venait à grossir au delà de 1024 octet, PHP allouera de nouveau de la mémoire et passera à la puissance de 2 supérieure, soit 2048 (2 puissance 11).

    C'est la raison pour laquelle tu ne constates pas de changement d'occupation de la mémoire alors que ton tableau grossit. PHP utilise la mémoire qui a déjà été allouée au tableau.
    et de ma très mauvaise mémoire (il faut faire avec mais sacré boulet ).

    Je l'ai donc fait sur l'essai simple mentionné ci-dessus et la mesure de mémoire semble fausse, donc merci de me dire quel est le problème :
    Code php : 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
                $debut = microtime(true);
                while (($line_csv = fgetcsv(CSVParser::getHandle(), $buffer, CSVParser::getSeparator(),
                    CSVParser::getEnclosure(),"")) !== false) {
     
                    code de la boucle
     
                    if ($nb_line >= 50000) break; //afin de pas planter à la fin
     
                } //fin de la boucle
                CSVImport::commit(); //on fait le commit en fin de boucle
     
                $fin = microtime(true);
                $temps = 1000*($fin - $debut);
                //Afficher le temps d'exécution
                $temps_de_chargement = number_format($temps, 3);
                echo "boucle exécutée en " . $temps_de_chargement . " msec";
    Ca dure au moins 10 minutes mais ça me dit
    boucle exécutée en 137,107.223 msec
    C'est quoi mon bug ?
    A demain

  4. #4
    Expert confirmé
    Avatar de Séb.
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    5 322
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 322
    Billets dans le blog
    17
    Par défaut
    rien que ça, c'est hyper long
    Il se cache quoi derrière tous es appels de $refrefTable ? Un SELECT à chaque fois ?

    Ca dure au moins 10 minutes mais ça me dit
    Ne complique pas les choses avec des conversions en millisecondes, Ton problème est de l'ordre de la minute/heure, pas de la milliseconde
    Tu exécutes ton script via le navigateur ou en ligne de commandes ?
    Fais un exit() après l'affichage du chrono au cas où autre chose exécuté APRÈS viendrait tout fausser.

  5. #5
    Membre Expert
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 493
    Billets dans le blog
    1
    Par défaut
    Merci pour ta réponse nocturne et ne pas m'être relevé en pleine nuit pour répondre

    Il se cache quoi derrière tous es appels de $refrefTable ? Un SELECT à chaque fois ?
    Pas de SELECT. Voici le code :
    Code php : 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
    switch (CSVParser::getCSVType())
                {
     
                    case "license":
     
                        // analyses
                        self::createLicensesObjects();
     
                        $this->errors = Record::analyze_license($this->refTableLicense);
                        //on effectue les analyses. Si une
                        // erreur est détectée, on renseigne la chaîne des erreurs ($this->errors)
                        if (Record::getLastError() == "no error")
                        {
                            CSVImport::putInDBLicense($this->refTableLicense,
                                $this->refPPP);
                        }
                   ....

    Code php : 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
        private function remove_utf8_bom_and_semicolon($text)
            {
                $text = preg_replace('~^\N{U+FEFF}~u', '', $text);
                $text = str_replace(';','',$text);
                return $text;
            }
     
        private function createLicensesObjects()
        {
            $tab = [];
            foreach ($this->data as $key => $value)
            {
                $tab[self::remove_utf8_bom_and_semicolon($key)] = self::remove_utf8_bom_and_semicolon($value);
            }
            $this->data = $tab;
     
            $this->ref_App = new AP_application(($this->data)['sesaid'], $this->data['applicationname']);
     
           //en tout, création de 12 objets mais y a que des affectations de variables
     
        $this->refTableLicense
            = new RefTableLicense;
     
        $this->refTableLicense->setRef_License($this->ref_App,
            $this->ref_Platform,
            $this->ref_Country,
            $this->ref_Location,
            $this->ref_Company,
            $this->ref_BU,
            $this->ref_Usermanager,
            $this->ref_User,
            $this->ref_USL_user_license,
            $this->ref_Domain,
            $this->ref_Mail,
            $this->ref_License);
        }
     
    public function setRef_License( $ref_app,
                                        $ref_platform,
                                        $ref_country,
                                        $ref_location,
                                        $ref_Company,
                                        $ref_BU,
                                        $ref_usermanager,
                                        $ref_US_user,
                                        $ref_USL_user_license,
                                        $ref_Domain,
                                        $ref_Email,
                                        $ref_license)
        {
            $this->ref_App = $ref_app;
            $this->ref_Platform = $ref_platform;
            $this->ref_Country = $ref_country;
            $this->ref_Location = $ref_location;
            $this->ref_Company = $ref_Company;
            $this->ref_BU = $ref_BU;
            $this->ref_Usermanager = $ref_usermanager;
            $this->ref_US_user = $ref_US_user;
            $this->ref_USL_user_license = $ref_USL_user_license;
            $this->ref_Domain = $ref_Domain;
            $this->ref_Email = $ref_Email;
            $this->ref_License = $ref_license;
        }

  6. #6
    Modérateur
    Avatar de grunk
    Homme Profil pro
    Lead dév - Architecte
    Inscrit en
    Août 2003
    Messages
    6 693
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Lead dév - Architecte
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2003
    Messages : 6 693
    Par défaut
    Avant de partir dans tous les sens :

    - Fait un fichier CSV de 10 lignes
    - Mesure le temps de chacun des appels de fonctions majeures
    - Lance le script

    Une fois que tu as identifié la partie qui prend le plus de temps :

    - Supprime les mesures de temps précédentes
    - Ajoute des mesures de temps dans la fonction identifiée comme étant problématique, pour isoler la partie la plus lente.
    - Lance le script

    Si cette partie lente est encore une fonction , répète l'opération précédente , jusqu'à arriver à l'instruction qui est réellement problématique.
    Une fois quetu auras identifié cela , on pourra te conseiller.

    Sans ca , ca me parait difficile d'avoir des remarque pertinentes.

    Si tu veux te faciliter un peu la vie sur la mesure de temps tu peux utiliser cette classe : https://github.com/grunk/Pry/blob/ma...Util/Bench.php

    qui s'utilise de la façon suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    require('bench.php');
     
    $b = new Pry\Util\Bench();
    $b->start();
     
    sleep(1); // Evidemment ce sleep représente le code à mesurer
    $b->add_flag('premier sleep');
     
    sleep(3); // Evidemment ce sleep représente le code à mesurer
    $b->add_flag('2eme sleep');
     
    $b->stop();
    var_dump($b->result());
    Ce qui affiche :
    array (size=3)
    'premier sleep' => float 1.0024399757385
    '2eme sleep' => float 4.0097258090973
    'total' => float 4.0097548961639
    Pry Framework php5 | N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

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

Discussions similaires

  1. [MySQL] Erreur pour écriture dans BDD
    Par laissaAnn dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 03/05/2013, 15h47
  2. Accès en écriture à la BdD impossible
    Par tssr2008 dans le forum WebDev
    Réponses: 3
    Dernier message: 20/06/2008, 00h48
  3. Réponses: 5
    Dernier message: 18/07/2007, 11h38
  4. Réponses: 1
    Dernier message: 24/10/2006, 12h10
  5. Meilleur méthode d'écriture en bdd - optimisation
    Par maximenet dans le forum SQL Procédural
    Réponses: 2
    Dernier message: 14/09/2006, 12h15

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