Zend FR

Consultez la FAQ sur le ZF avant de poster une question

Vous n'êtes pas identifié.

#1 03-04-2014 13:58:10

JGreco
Administrateur
Date d'inscription: 22-12-2012
Messages: 432

Insérer plusieurs milliers d'éléments dans une table doctrine

Bonjour, (pas oublié cette fois :p)

Toujours par rapport à mon projet en cours, j'ai récupéré dans mon UsersService, un certains nombre d'utilisateurs de mon ancienne base. (plusieurs milliers)
J'ai créée une Entité User qui correspond au mapping de ma nouvelle table User (dans ma nouvelle base).
L'objectif est d'insérer de la manière la plus optimale en évitant le maximum de requête à la base tous ces utilisateurs récupérés.

J'ai réussi jusqu’à présent en allouant a php.ini un memory limit  à 128M,  à transférer 7 900 utilisateurs (en utilisant une seule transaction sinon on divise par 10 :p)


Code:

[lang=php]
//datas = un array de plus de 45 000 utilisateurs
public function goTransfert($datas)
    {
        //on récupère ici la connection à la base de donnée mappé
        $this->em = $this->getServiceManager()->get('doctrine.entitymanager.orm_default');
        $connect = $this->em->getConnection();
//on lance une transaction, et une seule
        $connect->beginTransaction();
        foreach ($datas as $data) {
//on démarre le traitement
            $users = new User($data);
            $this->em->persist($users);
        }
//on lance les requete et on envoi
        $this->em->flush();
        $connect->commit();
    }

j'ai mit une limite à 8000 utilisateurs j'ai donc 8000 requêtes ... c'est beaucoup... le tout traité en quelques secondes en local.

Question n°1 : ais-je choisis la meilleure solution pour faire cela ? Je pense qu'on peut optimiser la méthode. La seule obligation c'est de passer par l'appli.

Question n°2 : Peut on faire en lieu et place des 8000 requêtes, une seule requête ? J'ai déjà avec les transactions restreint tout cela, mais le traitement est trop long et pour trop peu du traitement final espéré.

Question n°3 : Le serveur local, donne avec Zend developper tool un traitement des 8000 requetes traité en 1.22s, mais le chargement global de la page prend environ 5s, et pour une mémoire utilisé de 44M ces données vont changer sur un serveur de prod ou est-ce assez significatif comme indicateur de perf ? D'autre part, les 44mb renseigné ne sont pas cohérent avec la memory limit du php.ini puisque j'ai depassé à plusieurs reprise cette limite de 128mb utilisé, ce n'est donc pas la même ?

J'espère que je suis clair, sinon n'hésitez pas à me demander des informations.

Merci pour votre attention.

Dernière modification par JGreco (03-04-2014 13:59:51)


ZF2 et doctrine addict
profil stack overflow : http://stackoverflow.com/users/3333246/ … ab=profile

Hors ligne

 

#2 03-04-2014 14:53:43

Orkin
Administrateur
Lieu: Paris
Date d'inscription: 09-12-2011
Messages: 1261

Re: Insérer plusieurs milliers d'éléments dans une table doctrine

Salut pour ce genre de chose je t'ai déjà plus ou moins répondu comment je ferais wink.

Tu peux essayer un truc c'est créer une Collection et y passer tes entités. Ou alors tu peux aussi faire toi même une requête SQL sans passer par une entité doctrine du genre :
- Tu récupères les anciens utilisateurs (comme tu fais déjà)
- Tu fais une requête SQL dans ton repository qui va prendre en paramètre ton tableau et tu créés une seule requête d'insertion

Hors ligne

 

#3 03-04-2014 15:07:27

JGreco
Administrateur
Date d'inscription: 22-12-2012
Messages: 432

Re: Insérer plusieurs milliers d'éléments dans une table doctrine

Merci pour ta réponse Orkin,

J'ai déjà essayé de regarder avec les collections, et aussi de faire une requete d'insertion comme le permet MySQL, pour les INSERT multiples. Mais la méthode que j'ai écris plus haut est assez sympathique, et j'aurais aimé travailler plus avec cette méthode pour voir jusqu’où je peux l'optimiser, et tester ses limites.

J'ai déjà commencé à optimiser le process en utilisant les principes de batch processing décrit dans la doc de doctrine ici :
http://www.doctrine-project.org/2009/08 … ssing.html

En fait je remarque que l'insert de 20 000 enregistrements s'effectue en 10s, et les requêtes d'insert sont en réalité rapide le plus long c'est la création des entités. Ce qui, compte tenu de la quantité n'est pas mal du tout. Toutefois en local, ma page met longtemps à charger pour afficher le nombre de lignes insérés. Environ 15/20secondes, je pense que, du fait que je suis en local je recharge toute la config, modules etc ??? et c'est cela qui retarde le chargement des pages non ?


ZF2 et doctrine addict
profil stack overflow : http://stackoverflow.com/users/3333246/ … ab=profile

Hors ligne

 

#4 03-04-2014 16:42:48

Orkin
Administrateur
Lieu: Paris
Date d'inscription: 09-12-2011
Messages: 1261

Re: Insérer plusieurs milliers d'éléments dans une table doctrine

C'est minime le gain de perf de la conf en cache par rapport à la durée de tes traitements. C'est la création des entités et tout le cycle de persistance qui prend du temps. Donc je te propose de l'insérer directement sans créer les entités en passant par une requête SQL. Après c'est toi qui voit, pour un de mes projets j'ai 75 000 à insérer, je le fais une fois pour générer la base pour se faire je suis obligé d'augmenter temporairement la limite de mémoire de php et le temps d’exécution autorisé pour php. Donc soit tu fais comme ça soit tu passes directement par SQL et tu vas aussi vite et ça fait la même chose. Tu peux toujours garder un système de foreach et compagnie c'est juste que tu créés pas les entités (qui au final sert à rien puisque tu les réutilises pas).

Hors ligne

 

#5 03-04-2014 18:18:15

JGreco
Administrateur
Date d'inscription: 22-12-2012
Messages: 432

Re: Insérer plusieurs milliers d'éléments dans une table doctrine

J'avoue que tu as raison sur le principe, surtout si je les réutilise pas. Je pense que de toute façon je garde cette procédure quelques part, je la réutilisera surement dans d'autre traitements moins gourmand et plus utile au niveau de la gestion des entités..plus je découvre doctrine et zf2 plus je me rend compte que c'est puissant....

Par contre passer directement par SQL, c'est faire une createNativeQuery ?? Je t'avoues que je ne connais pas du tout la syntaxe d'une telle requête pour un insert massif, tu peut m'aiguiller s'il te plait ?

Merci pour ton temps, en tous cas, encore une fois tu es de bon conseil smile


ZF2 et doctrine addict
profil stack overflow : http://stackoverflow.com/users/3333246/ … ab=profile

Hors ligne

 

#6 03-04-2014 18:38:59

Orkin
Administrateur
Lieu: Paris
Date d'inscription: 09-12-2011
Messages: 1261

Re: Insérer plusieurs milliers d'éléments dans une table doctrine

Oui c'est une createNativeQuery ou un truc du genre (je l'ai plus en tête). Ben c'est du SQL bateau :

Code:

[lang=sql]INSERT INTO nomdematable (id, champ1, champ2, etc ...) VALUES (NULL, 'value1', 'value2', etc ...), (NULL, 'autrevalue1', 'autrevalue2', etc ...);

Hors ligne

 

Pied de page des forums

Propulsé par PunBB
© Copyright 2002–2005 Rickard Andersson
Traduction par punbb.fr

Graphisme réalisé par l'agence Rodolphe Eveilleau
Développement par Kitpages