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

Entity Framework Discussion :

[Optimisation] Insert avec Entity Framework


Sujet :

Entity Framework

  1. #1
    Membre chevronné Avatar de Er3van
    Homme Profil pro
    Architecte Logiciel
    Inscrit en
    Avril 2008
    Messages
    1 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte Logiciel
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2008
    Messages : 1 430
    Points : 2 227
    Points
    2 227
    Par défaut [Optimisation] Insert avec Entity Framework
    Hello,

    Je suis aujourd'hui confronté à un problème de performances, comme dit dans le titre, sur des requêtes d'insertion.
    Ma crainte c'est que la réponse soit simplement le fait c'est la limite d'Entity Framework, que les Insert sont lents de façon inhérente à la techno (plus fait pour des "select/update" unitaire j'en conviens.

    Pour préciser un peu plus le soucis, il s'agit d'insertions "massives".
    Le programme en question extrait d'un fichier XML des lignes à insérer en base, environ 500 000 dans le fichier. Le traitement prend actuellement plusieurs heures (environ 4h), ce qui n'est pas compatible avec les contraintes métiers qui sont derrières.

    Entity Framework avait été choisi à l'époque pour simplifier la vie de la maintenance (car Entity est utilisé pour d'autres applications) et parce que le problème de performance ne se posait pas à l'époque car le volume de données a été mal estimé par le client (~10x plus important que prévu)

    Bref, j'ai essayé d'optimiser la structure de la base, supprimer des index pour gagner du temps, rien n'y fait ! (A noter qu'une contrainte réseau accentue le phénomène... comme si ça ne suffisait pas !)

    Toujours est-il que ma question est là suivante :
    Peut-on faire quelque chose pour améliorer ça avec Entity Framework ? Faut-il se rabattre sur une solution "à la mano" type requête SQL "en dur" (car NHibernate semble trop coûteux à mettre en place du fait de l'état d'avancement) ?
    J'ajoute que les solutions type Bulk ou SSIS ont été exclues pour des raisons d'infra (pas d'"applicatif" sur le server SQL...).

    Si cela peut aider voici un bon de code qui fait l'insertion en Linq to SQL :

    Code c# : 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
     
    using (CoverEntities context = new CoverEntities())
                {
                    try
                    {
                        T_G61_ITEMS Item = null;
     
                        // Get the XXX by ID
                        var xxx = context.XXX.First(x => x.ID == XID);
     
                        // Check if there is already an item for the given XXX, language and item
                        // It should only happen for some items described in multiple rows
                        var ExistingItems = from i in context.ITEMS
                                            where i.ITEMS_NM_ITEM.Equals(ItemID, StringComparison.CurrentCultureIgnoreCase)
                                            && i.ITEMS_ID_LANGUAGE_ID.Equals(LanguageID, StringComparison.CurrentCultureIgnoreCase)
                                            && i.XXX.ID == XXX
                                            select i;
     
                        // If there is no existing item
                        if (ExistingItems.ToList().Count == 0)
                        {
                            // Then create one
                            Item = new ITEMS
                            {
                                ITEMS_ID_LANGUAGE_ID = LanguageID,
                                ITEMS_NM_ITEM = ItemID,
                                ITEMS_NM_VALUE = ItemValue
                            };
     
                            // Add the reference to the XXX
                            xxx.ITEMS.Add(Item);
                        }
                        else
                        {
                            // Update the existing item
                            Item = ExistingItems.First();
                            Item.ITEMS_NM_VALUE = Item.ITEMS_NM_VALUE.TrimEnd() + ' ' + ItemValue.TrimStart();
                        }
     
                        // Save the context for change commit
                        context.SaveChanges();           
                    }
                    catch (Exception e)
                    {
                        throw new DatabaseException(e.Message, e.InnerException);
                    }
                }

    PS : J'ai remplacé certains termes mais j'espère ne pas avoir cassé la sémantique...


    Merci d'avance !
    One minute was enough, Tyler said, a person had to work hard for it, but a minute of perfection was worth the effort. A moment was the most you could ever expect from perfection.

    -- Chuck Palahniuk, Fight Club, Chapter 3 --

  2. #2
    Membre émérite
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Avril 2006
    Messages
    1 627
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2006
    Messages : 1 627
    Points : 2 331
    Points
    2 331
    Par défaut
    Pareil, j'ai eu un projet de migration de données, EF ok pour quelques milliers de lignes, mais ensuite ça ne tenait plus la route. Une procédure stockée appelée par un agent obéissant à un calendrier a fait face sans souci !

    Sinon, une réplication à sens unique ne pourrait pas résoudre le problème ? Genre Fusion ?

  3. #3
    Membre chevronné Avatar de Er3van
    Homme Profil pro
    Architecte Logiciel
    Inscrit en
    Avril 2008
    Messages
    1 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte Logiciel
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2008
    Messages : 1 430
    Points : 2 227
    Points
    2 227
    Par défaut
    La réplication supposerait que je sois maître des données entrantes, malheureusement ces données provienne d'une entreprise externe... (à moins que j'ai mal compris ce que tu entends par réplication).

    En ce moment je regarde la solution "requêtes en dur", on verra si les performances tiennent la route !
    One minute was enough, Tyler said, a person had to work hard for it, but a minute of perfection was worth the effort. A moment was the most you could ever expect from perfection.

    -- Chuck Palahniuk, Fight Club, Chapter 3 --

  4. #4
    Membre émérite
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Avril 2006
    Messages
    1 627
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2006
    Messages : 1 627
    Points : 2 331
    Points
    2 331
    Par défaut
    En réplication sur SQL Server on distingue le push (le serveur envoie les données via notification) et le pull (l'abonné interroge le serveur pour identifier les données à rapatrier). Dans les deux cas cela implique la mise en place d'un serveur de publication sur le serveur source, ce qui n'est pas évident dans ton cas apparemment.

  5. #5
    Membre chevronné Avatar de Er3van
    Homme Profil pro
    Architecte Logiciel
    Inscrit en
    Avril 2008
    Messages
    1 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte Logiciel
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2008
    Messages : 1 430
    Points : 2 227
    Points
    2 227
    Par défaut
    Non, pas évident du tout ! Merci pour l'idée en tout cas !

    Là je viens de passer en requête "en dur", y a pas photo.... j'suis sur un truc qui est de l'ordre de 50 000 insertions par minutes en local, contre 7 000 auparavant !

    En regardant un peu dans le détail, j'ai l'impression que c'est l'auto-incrémente qui fait merder Entity Framework, il fait systématiquement (au milieu de l'insert) :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    select [ITEMS_ID_ITEM_ID]
    from [dbo].[T_G61_ITEMS]
    where @@ROWCOUNT > 0 and [ITEMS_ID_ITEM_ID] = scope_identity()

    Alors que c'est inutile et consommateur...

    J'essaye de voir si y a moyen de le paramétrer mais je vois pas trop à quel niveau...
    One minute was enough, Tyler said, a person had to work hard for it, but a minute of perfection was worth the effort. A moment was the most you could ever expect from perfection.

    -- Chuck Palahniuk, Fight Club, Chapter 3 --

  6. #6
    Rédacteur
    Avatar de Nathanael Marchand
    Homme Profil pro
    Expert .Net So@t
    Inscrit en
    Octobre 2008
    Messages
    3 615
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Expert .Net So@t
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2008
    Messages : 3 615
    Points : 8 080
    Points
    8 080
    Par défaut
    Pour avoir eu le même cas que toi, (batch journalier de millions de lignes qui durait 48h) je suis passé par le bulk insert et la commande merge (c'était une fusion/insertion): 4min de batch
    J'ai pas compris ton argument de "pas d'applicatif sur le serveur sql"

  7. #7
    Membre chevronné Avatar de Er3van
    Homme Profil pro
    Architecte Logiciel
    Inscrit en
    Avril 2008
    Messages
    1 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte Logiciel
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2008
    Messages : 1 430
    Points : 2 227
    Points
    2 227
    Par défaut
    Citation Envoyé par Nathanael Marchand Voir le message
    Pour avoir eu le même cas que toi, (batch journalier de millions de lignes qui durait 48h) je suis passé par le bulk insert et la commande merge (c'était une fusion/insertion): 4min de batch
    Comment c'est possible de réduire autant ??? O.o
    Tu paramètres le merge à quel niveau du coup ?

    Citation Envoyé par Nathanael Marchand Voir le message
    J'ai pas compris ton argument de "pas d'applicatif sur le serveur sql"
    Moi non plus je l'ai pas compris... (ce n'est pas "mon" argument... celui de l'admin SQL Server, pas basé en France dont intouchable...).
    One minute was enough, Tyler said, a person had to work hard for it, but a minute of perfection was worth the effort. A moment was the most you could ever expect from perfection.

    -- Chuck Palahniuk, Fight Club, Chapter 3 --

  8. #8
    Inactif  
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Janvier 2007
    Messages
    6 604
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet NTIC

    Informations forums :
    Inscription : Janvier 2007
    Messages : 6 604
    Points : 13 314
    Points
    13 314
    Par défaut
    Citation Envoyé par Er3van Voir le message
    J'ajoute que les solutions type Bulk ou SSIS ont été exclues pour des raisons d'infra (pas d'"applicatif" sur le server SQL...).
    Je ne comprends pas cette phrase.
    Pourquoi avoir exclu SSIS qui semble la seule solution logique ici ?

    Je ne réponds pas aux questions techniques par MP ! Le forum est là pour ça...


    Une réponse vous a aidé ? utiliser le bouton

    "L’ennui dans ce monde, c’est que les idiots sont sûrs d’eux et les gens sensés pleins de doutes". B. Russel

  9. #9
    Rédacteur
    Avatar de Nathanael Marchand
    Homme Profil pro
    Expert .Net So@t
    Inscrit en
    Octobre 2008
    Messages
    3 615
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Expert .Net So@t
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2008
    Messages : 3 615
    Points : 8 080
    Points
    8 080
    Par défaut
    Le but de mon batch etait d'integrer un fichier de mise à jour client. Or cette mise à jour n'était pas incrémentale: on recevait tous les jours toute la base client! Dans le premier jet, ligne par ligne en C# je parsais le fichier puis allais vérifier en base si je devais faire un insert ou un update. C'est bien ok pour 1000 lignes mais des lors qu'on a 8millions...
    Alors la solution a été de parser le fichier recu pour en faire un fichier CSV. Ce CSV est mis sur un repertoire réseau. Bulk Insert du fichier dans une table temporaire et enfin merge entre la table temporaire et la table réelle.

  10. #10
    Membre chevronné Avatar de Er3van
    Homme Profil pro
    Architecte Logiciel
    Inscrit en
    Avril 2008
    Messages
    1 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte Logiciel
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2008
    Messages : 1 430
    Points : 2 227
    Points
    2 227
    Par défaut
    Citation Envoyé par Bluedeep Voir le message
    Je ne comprends pas cette phrase.
    Pourquoi avoir exclu SSIS qui semble la seule solution logique ici ?
    Car SSIS n'est pas appointé (dans mon entreprise) comme solution valide, excepté pour de la BI, sur des serveurs mutualisés... C'est aussi idiot que ça.
    En gros c'est l'admin qui n'est pas d'accord. Pas négociable.... (mais je suis le premier à avoir gueulé si ça peut te rassurer...)
    One minute was enough, Tyler said, a person had to work hard for it, but a minute of perfection was worth the effort. A moment was the most you could ever expect from perfection.

    -- Chuck Palahniuk, Fight Club, Chapter 3 --

  11. #11
    Membre chevronné Avatar de Er3van
    Homme Profil pro
    Architecte Logiciel
    Inscrit en
    Avril 2008
    Messages
    1 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte Logiciel
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2008
    Messages : 1 430
    Points : 2 227
    Points
    2 227
    Par défaut
    Finalement, après avoir comparé les performances des cas suivants :

    - Utilisation EF standard pour insertion
    - Utilisation EF avec proc stock pour insertion
    - Utilisation "directe" proc stock pour insertion
    - Insertion "directe"

    Les meilleures performances sont incontestablement pour la dernière solution.
    Certes, c'est pas propre, mais compte tenu du volume en question : tant pis !

    J'ai juste rajouter une p'tite classe qui gère la connexion avec un singleton pour éviter les ouvertures/fermetures intempestive de la connexion, ça gagne encore un peu de temps.

    L'option BulkCopy avait aussi été envisagée, mais beaucoup plus d'impact au niveau du code, et gestion compliquée d'une collection (gigantesque) d'objets.

    Merci pour votre aide !
    One minute was enough, Tyler said, a person had to work hard for it, but a minute of perfection was worth the effort. A moment was the most you could ever expect from perfection.

    -- Chuck Palahniuk, Fight Club, Chapter 3 --

  12. #12
    Inactif  
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Janvier 2007
    Messages
    6 604
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet NTIC

    Informations forums :
    Inscription : Janvier 2007
    Messages : 6 604
    Points : 13 314
    Points
    13 314
    Par défaut
    Citation Envoyé par Er3van Voir le message
    Certes, c'est pas propre,
    C'est en tout cas bien plus propre que d'utiliser EF dans ce cas !

    Ici, tu travaille a priori sur de la donnée "brut", il n'y donc que des inconvénients (et aucune logique) à utiliser une couche d'encapsulation orientée "objets métier".

    Je ne réponds pas aux questions techniques par MP ! Le forum est là pour ça...


    Une réponse vous a aidé ? utiliser le bouton

    "L’ennui dans ce monde, c’est que les idiots sont sûrs d’eux et les gens sensés pleins de doutes". B. Russel

  13. #13
    Membre chevronné Avatar de Er3van
    Homme Profil pro
    Architecte Logiciel
    Inscrit en
    Avril 2008
    Messages
    1 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte Logiciel
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2008
    Messages : 1 430
    Points : 2 227
    Points
    2 227
    Par défaut
    C'est en tout cas bien plus propre que d'utiliser EF dans ce cas !
    Oui et non, on perd en cohérence d'ensemble (logique "logicielle") et en maintenabilité, mais effectivement on gagne en efficacité et en logique "informatico-technique".

    Cela dépend du contexte de travail tu me diras, dans une SSII ou une boite spécialisée en informatique type Editeur Logiciel, la logique métier serait la même que la logique informatique, donc aucun soucis, mais ce n'est pas mon cas.
    One minute was enough, Tyler said, a person had to work hard for it, but a minute of perfection was worth the effort. A moment was the most you could ever expect from perfection.

    -- Chuck Palahniuk, Fight Club, Chapter 3 --

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

Discussions similaires

  1. Pour instancier le context avec Entity Framework
    Par aboily dans le forum Entity Framework
    Réponses: 0
    Dernier message: 26/05/2010, 06h28
  2. Problème Ajout Donnée avec Entity Framework
    Par Invité dans le forum Linq
    Réponses: 4
    Dernier message: 14/10/2009, 14h16
  3. Pb de création de modéle avec entity framework
    Par rangdalf dans le forum Connexion aux bases de données
    Réponses: 2
    Dernier message: 25/06/2009, 22h34
  4. Probleme de connexion avec Entities Framework
    Par gstrit dans le forum Général Dotnet
    Réponses: 4
    Dernier message: 09/06/2009, 09h09
  5. Insert avec zend framework
    Par rugby_roux dans le forum Zend
    Réponses: 1
    Dernier message: 30/01/2007, 17h22

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