Salut les ami(s)s,

Bon je viens vers vous car je ne sais pas trop^comment m'y prendre.Je dois importer un fichier excel csv de 500.000mil ligne dans une base de donnée.L'importe se passe très bien cependant j'aimerai optimiser mon code.Au début l'import faisait plus d'une heure mais j'ai reussi à l'optimiser et faire en sorte que cela fasse 25min maintenant.Cependant j'aimerai que l'import sois en 10s ou 15s max.

voici mon code et j'uitilise symfony et League csv pour l'import.La fonction en bas là est celui qui calcul le temps d'execution.

 public function execute(InputInterface $input, OutputInterface $output)
    {
        $time_start = $this->microtime_float();
        $this->em->getConnection()->getConfiguration()->setSQLLogger(null);
        $io = new SymfonyStyle($input, $output);
        $io->title('Import de fichier csv...');
        $tab_competitor = [];
        $tab_athlete = [];

        $reader = Reader::createFromPath('%kernel.root_dir%/../src/Data/MOCK_DATA.csv');

        $results = $reader->fetchAssoc();

        $resultas = iterator_to_array($results);

        $io->progressStart(iterator_count($results));

        $countC = $this->em->getRepository(Competitor::class)->detectC();

        if ($countC != 0)
        {
            $competitors = $this->em->getRepository(Competitor::class)->findAll();
            /** @var Competitor $value */

            foreach ($competitors as $value)
            {
                $tab_competitor[$value->getCategory()] = $value;
            }
        }

        $countA =  $this->em->getRepository(Athlete::class)->detectA();

        if ($countA != 0)
        {
            $athletes = $this->em->getRepository(Athlete::class)->findAll();

            /** @var Athlete $values */
            foreach ($athletes as $values)
            {
                $tab_athlete[$values->getFirstname().$values->getLastname()] =  $values;
            }
        }

//        $check = false;

        foreach ($resultas as $row)
        {
//            //do a lookup for existing Competitor matching some combination of fields
            $exist = array_key_exists($row['category'], $tab_competitor);
            if ($exist) {

                $competitor =  $tab_competitor[$row['category']];
            }
            else {
//                $check = true;
                // or create new Competitor
                $competitor = (new Competitor())
                    ->setCategory($row['category'])
                    ->setCompetition($row['competition'])
                ;
                $this->em->persist($competitor);
                $tab_competitor[$row['category']] = $competitor;
            }

            $exist = array_key_exists($row['first_name'], $tab_athlete);
            if ($exist) {
                $athlete =  $tab_athlete[$row['first_name'].$row['last_name']];
                $athlete->setCompetitor($competitor);
                $this->em->persist($athlete);
            } else {
//                $check = true;
                // or create a new athlete
                $athlete = (new Athlete())
                    ->setFirstname($row['first_name'])
                    ->setLastname($row['last_name'])
                    ->setDateofbirth($row['date_of_birth'])
                    ->setWeight($row['weight']);
                $athlete->setCompetitor($competitor);
                $this->em->persist($athlete);
                $tab_athlete[$row['first_name'].$row['last_name']] = $athlete;
            }

            $io->progressAdvance();
        }
      if($check) {
            $this->em->flush();
     }

        $time_end = $this->microtime_float();

        $io->success('Upload succes');
        $io->success('tous c\'est bien passé');

        $time = $time_end - $time_start;

        echo "Did nothing in $time seconds\n";

        return new Response("BD ok");
    }

    public function microtime_float()
    {
        list($usec, $sec) = explode(" ", microtime());
        return ((float)$usec + (float)$sec);
    }

Ce que je voudrai faire est que mon idée est de diviser le tableau $result en plusieur partie pour rendre le traitement plus rapide mais je ne sais comment m'y prendre c'est ça le problème.

3 réponses


Lartak
Réponse acceptée

Bonjour.
Tu peux par exemple utiliser la fonctionarray_chunk:

Sépare un tableau en tableaux de taille inférieure
Description

array_chunk(array $array, int $size [, bool $preserve_keys = FALSE ]) : array

Sépare le tableau array en plusieurs tableaux comptant size éléments. Il est aussi possible que le dernier tableau contienne moins de valeurs.

_Source : PHP: array_chunk - Manual_

Par contre ton fichier contient deux fois la même fonction : public function microtime_float(), de plus que pour la première il y a du code qui se trouve à l'extérieur de celle-ci.

CedLP
Auteur

Merci pour la function array_chunk c'est bien ce que je voulais Lartak,
J'ai déjà pu diviser le temps en 2.

pour le code c'été le copie coller qui avait coser désolé :D

CedLP
Auteur

Merci Lartak, la fonction m'a aider et ja'ai fait quelque amélioration et c'est nickel :)