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

ORM PHP Discussion :

[Doctrine] Import de donnée et diff?


Sujet :

ORM PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 28
    Par défaut [Doctrine] Import de donnée et diff?
    Bonjour,

    J'aurai aimé avoir quelques conseil sur un problème qui me plombe un peu le moral...

    Dans les grandes lignes, je suis sur un projet ou je dois conçevoir une base de donnée avec la gestion de configuration...

    En faite lors d'une mise à jour, l'utilisateur envoie sont fichier excel. Je dois remplir ma base de donnée en fonction des données contenu dans ce fichier. Ces derniers sont les données qui seront "valide" tant qu'une mise à jour n'a pas été faite. Si une entrée de la base de donnée n'est plus visible sur le fichier excel alors je met l'entrée en obsolete (mais je le conserve pour la journalisation, merci softDelete et Versionable)

    Alors j'ai des problèmes sur comment faire un diff avec Doctrine_Collection? car j'ai quelques 500 entrées dans le fichier Excel et dans MySQL...
    J'ai cru lire qu'il y avait une méthode snapshot dans Doctrine_Collection qui permet de faire un diff.

    Autrement, j'ai tenter une approche plutot "bourrin", et la je tombe sur des problème de perf...

    Bref quelqu'un aurai une idée de comment réaliser ça? car je commence a sécher...

    Merci!

  2. #2
    Expert confirmé
    Avatar de Michel Rotta
    Homme Profil pro
    DPO
    Inscrit en
    Septembre 2005
    Messages
    4 954
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : DPO
    Secteur : Distribution

    Informations forums :
    Inscription : Septembre 2005
    Messages : 4 954
    Par défaut
    Tu lis ton fichier excel comment ? Tu en fait quoi (traitement direct où un tableau interne,...) ?

    Quid si une ligne est modifiée ? L'ancienne disparait ? Pourquoi un traitement particulier pour les Effacements ? Quid en cas de création d'une ligne ?

    Je vois bien la méthode bourin, je charge toutes les lignes utilisateurs d'un coup et je fais les modifs dans les objets, puis je sauvegarde. J'imagine la tête de la mémoire quant elle voit arriver le paquet de données.

    Le problème est que je ne vois pas beaucoup d'autres solutions que de comparer les deux entrées.

    Une méthode moins bourin (quoique) pour chaque ligne, faire la mise à jours. Intégrer un "jeton" dans la base pour avoir la version de la donnée. Puis "supprimer" les données non mises à jour. Sans compter le problème des créations.

    Un méthode bourin sophistiquée ? Tu rajoutes un jeton (timecode) pour les données. Tu crées systématiquement un nouvel enregistrement pour chaque donnée. Tu "supprimes" tous ce qui n'est pas a jour. Coté perf, cela devrait être mieux, moins de code, pas de lecture, de toutes les manières, tu es bon pour écrire dans les 500 lignes... Par contre, 500 requêtes. Quoique, tu dois pouvoir jouer sur les transaction. En envoyant tes modifications par transactions d'un paquet de X (a mettre en paramètre pour pouvoir optimiser en fonction de la configuration qui peut évoluer) tu devrais encore gagner pas mal de temps. Par contre, la base va gonfler (en fonction des fréquences de mises à jours).

    Autre solution, tu envoies dans une table temporaire, puis tu lances une proc stok sur la base pour faire les vérifications et modification, suppression, création,...


    Les notions de diff dans le doctrine_collection ne vont pas t'aider. En effet, c'est plutôt dans le style je récupère une collection et je n'envoie que les effacement ou insertion ou modification que j'ai fais sur cette collection. Mais une collection de 500 en mémoire risque d'être un peu lourde à gérer pour un serveur.


    Maintenant tu peux aussi envisager un traitement en batch si tu crains un encombrement du serveur, tu stock le fichier récupéré sur le serveur et dans une table de fichiers à traiter et tu lance régulièrement une commande qui ne traite qu'un fichier à la fois. L'utilisateur va avoir confirmation du upload de ces informations sur le serveur, puis, une fois le fichier traité, il aura l'information sur l'écran, s'il rafraichi. Ou le lendemain quant il se reconnecte.

    Désolé de ne pas avoir de solution unique, mais j'espère que cette collection de pistes pourra t'aider.

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 28
    Par défaut
    Merçi d'avoir répondu.

    Alors aujourd'hui je lis mon fichier excel via la librairie PHPExcel, du faite que j'ai une diversité de fichiers excel (2003 binaire, 2007...).

    Donc je lis le fichier avec PHPExcel qui me renvoie un objet dont je stock pour un traitement plus facile pour la suite.

    Citation Envoyé par Michel Rotta
    Quid si une ligne est modifiée ? L'ancienne disparait ? Pourquoi un traitement particulier pour les Effacements ? Quid en cas de création d'une ligne ?
    Alors si une ligne est modifiée, je garde l'ancienne entrée, mais je rajoute une nouvelle entrée avec sa nouvelle version. En ce qui concerne le traitement si particulier des effacements, c'est que je dois garder une certraine traçabilité sur les évolutions des objets que je manipule, c'est une contrainte obligatoire malheureuement...

    Sur la création d'une ligne, je dois rajouter l'entrée et mettre sa version à 1. (Il faut savoir qu'en faite je dois migrer des fichiers excels vers une base de donnée..., ce qui est pas simple du tout! Car aujourd'hui tout est gérer avec excel, c'est à dire des fichiers excels tous les 3 mois depuis 5ans qui recoupe avec d'autres fichiers excels... bref un petit bordel monstre...)

    Citation Envoyé par Michel Rotta
    Je vois bien la méthode bourin, je charge toutes les lignes utilisateurs d'un coup et je fais les modifs dans les objets, puis je sauvegarde. J'imagine la tête de la mémoire quant elle voit arriver le paquet de données.
    Oui... La mémoire prend un coup sur la tête , et puis le timeout est assez conséquent...

    Citation Envoyé par Michel Rotta
    Le problème est que je ne vois pas beaucoup d'autres solutions que de comparer les deux entrées.
    Oui, et c'est ça le souci...

    Bah pour la gestion des versions, j'utilise le behavior "Versionable" de Doctrine.

    Citation Envoyé par Michel Rotta
    Une méthode moins bourin (quoique) pour chaque ligne, faire la mise à jours. Intégrer un "jeton" dans la base pour avoir la version de la donnée. Puis "supprimer" les données non mises à jour. Sans compter le problème des créations.
    Bah j'ai pensé a ça en 1er ce weekend... Faire une table de hash histoire de trouver rapidement les entrées sans leur version, en ce qui concerne le changement de version, bah au pire je créer une version à chaque fois, ça ne me dérange pas trop (quoi que j'aurai des données en redondance, le versionning permet d'éviter les redondances...). Puis j'aurai un array de clés des entrées a jours, dont avec la clause "NOT IN (entrées...)" je pourrai tagger ceux qui sont obsolètes!

    Question : Le behavior Versionable marche comment? à chaque save il incrémente? ou il fait un incrémente intéligent en vérifiant s'il y a une modification? (je crois que je vais faire un test pour savoir comment il fonctionne en détail) car s'il est intéligent, alors je ne me prend plus la tête!

    Citation Envoyé par Michel Rotta
    Un méthode bourin sophistiquée ? Tu rajoutes un jeton (timecode) pour les données. Tu crées systématiquement un nouvel enregistrement pour chaque donnée. Tu "supprimes" tous ce qui n'est pas a jour. Coté perf, cela devrait être mieux, moins de code, pas de lecture, de toutes les manières, tu es bon pour écrire dans les 500 lignes... Par contre, 500 requêtes. Quoique, tu dois pouvoir jouer sur les transaction. En envoyant tes modifications par transactions d'un paquet de X (a mettre en paramètre pour pouvoir optimiser en fonction de la configuration qui peut évoluer) tu devrais encore gagner pas mal de temps. Par contre, la base va gonfler (en fonction des fréquences de mises à jours).
    Alors le souci avec ça c'est pour la gestion des données...
    Alors j'ai 2 types de mises à jours... mais on va dire que la base des données des entrées sont à mettre à jours tous les 3 mois (ça va c'est large), parcontre ya beaucoup de données...

    Sinon les 500 entrées, c'est le minimum... J'ai des fichiers avec plus de 1000 entrées... C'est assez lent sur le traitement, j'ai mis un timeout a 180s (faut savoir que l'application est interne, donc pas sur le web).

    Citation Envoyé par Michel Rotta
    Autre solution, tu envoies dans une table temporaire, puis tu lances une proc stok sur la base pour faire les vérifications et modification, suppression, création,...
    J'y ai pensé aussi, mais bon... faut que je reproduise le behavior versionnable. Je pense le faire en dernier recours si je trouve pas la solution miracle... Mais j'avoue que point de vue temps d'execution et mémoire, je serai un peu plus serein.

    Citation Envoyé par Michel Rotta
    Les notions de diff dans le doctrine_collection ne vont pas t'aider. En effet, c'est plutôt dans le style je récupère une collection et je n'envoie que les effacement ou insertion ou modification que j'ai fais sur cette collection. Mais une collection de 500 en mémoire risque d'être un peu lourde à gérer pour un serveur.
    Merci pour l'info!

    Citation Envoyé par Michel Rotta
    Maintenant tu peux aussi envisager un traitement en batch si tu crains un encombrement du serveur, tu stock le fichier récupéré sur le serveur et dans une table de fichiers à traiter et tu lance régulièrement une commande qui ne traite qu'un fichier à la fois. L'utilisateur va avoir confirmation du upload de ces informations sur le serveur, puis, une fois le fichier traité, il aura l'information sur l'écran, s'il rafraichi. Ou le lendemain quant il se reconnecte.
    J'ai pensé a cette solution, je l'ai utilisé dans le passé. Parcontre, j'ai pensé proposer d'avoir un apperçu à l'utilisateur avant de sauvegarder... Je pense employer cette solution si aucune ne me plaise.

    Citation Envoyé par Michel Rotta
    Désolé de ne pas avoir de solution unique, mais j'espère que cette collection de pistes pourra t'aider.
    Merci!

    Sinon j'ai pensé pourquoi pas faire un fetch en array, puis traiter le tout comme un array et le charger dans la doctrine collection?

    Bon je vais faire des tests et donner mes résultats, je pense que ça servirai a quelqu'un

  4. #4
    Expert confirmé
    Avatar de Michel Rotta
    Homme Profil pro
    DPO
    Inscrit en
    Septembre 2005
    Messages
    4 954
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : DPO
    Secteur : Distribution

    Informations forums :
    Inscription : Septembre 2005
    Messages : 4 954
    Par défaut
    Je n'ai jamais utilisé le plugins versionable, mais j'ai bien peur qu'il mette un numéro de version par enregistrement. Dans ton cas, je pense que tu aurait intérêt à avoir un numéro de version par téléchargement. A mon avis, exit le plugin.

    Tous mettre dans un fecht et créer à partir de là ! C'est comme créer les 500 en mémoire et envoyer d'un coup. Il va falloir doper le serveur !

    A priori, tu peux te passer de vérification avec l'existant, puisque tu crées ce qui n'existe pas, modifie ce qui existe et supprime ce qui n'existe plus. La lecture de la table n'apporte rien. Donc un ajout général, par paquets (en utilisant les transactions). Et épurer régulier la base en ce basant sur une table intermédiaire qui reprendra l'id de l'utilisateur, la version, la date ...

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 28
    Par défaut
    Alors j'ai une bonne nouvelle! Le behavior Versionable sous doctrine est pas "con". Elle fait une monté de révision si une réel modification a été apporté.

    Bon a savoir!

    Sinon pour les diff, alors pour faire simple, je vais tout simplement faire des updates sur les entrées existantes (via la clé de hash) et comme versionable est intéligent bah il rajoutera une monté en révision si ya une réel modification. Puis par la suite, je delete tous ceux qui ne correspond pas dans ma table ayant les clés de hash à jours (merci la clause "NOT IN").
    Par la suite, je fais les inserts.

    Pour les soucis de traitement, je pense faire ça en bash, histoire de ne pas être pénaliser par les timeout avec un système de log pour savoir l'état du traitement.

    Je metterai des retours de perf!

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 28
    Par défaut
    Bon retour sur le feedback au cas ou les gens auront un truc de ce genre à faire!

    Alors solution opté c'est 2 types de versionable... ça peut paraitre lourd mais justifié!

    J'utilise le behavior versionable de doctrine pour versioné les modifications (utile quand quelqu'un modifie et cela permet d'avoir un historique).

    Autrement, je fetch une doctrine_collection et j'index ma collection via le hash donnée (le hash est un simple md5 sur certains objets, et sur d'autre un numéro de référence unique...).
    Je modifie tout sur mes collections, et à la fin, la class doctrine_collection dispose d'une méthode hasModified qui permet de savoir si la collection à été modifié. Si c'est le cas je save la collection (Parcontre il fait une requete par item...). grosomodo 1000 req d'insert en 8s par là ça reste raisonable...

    bref... ça marche et le client est content! c'est ce qui est le plus important!

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

Discussions similaires

  1. Importer des données grace a des *.cvs dans MySQL
    Par Mic0001 dans le forum Installation
    Réponses: 3
    Dernier message: 05/01/2005, 19h26
  2. [CR]Importer des données d'une feuille excel
    Par rolan dans le forum SAP Crystal Reports
    Réponses: 3
    Dernier message: 17/12/2004, 22h32
  3. Réponses: 3
    Dernier message: 13/12/2004, 13h54
  4. Importer des données dans sql server avec DELPHI ???
    Par moutanakid dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 11/08/2004, 17h22
  5. Importation de données postgresql
    Par ythierrin dans le forum PostgreSQL
    Réponses: 2
    Dernier message: 10/10/2003, 22h18

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