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

VB.NET Discussion :

Optimisation d'un traitement lourd [Débutant]


Sujet :

VB.NET

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre actif
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2010
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Mars 2010
    Messages : 71
    Par défaut Optimisation d'un traitement lourd
    Bonsoir mes amis,
    j'ai un formulaire qui génère un fichier EXCEL pour les mouvements de stock de 1500 articles :

    Le problème c'est il prend beaucoup du temps environ 30 minutes et au même temps il se plante

    Voici le code de traitement que j'ai fait :
    Code : 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
    Private Sub traitement()
            Try
                Dim _date1 As New Date(DateTimePicker1.Value.Year, DateTimePicker1.Value.Month, DateTimePicker1.Value.Day, 0, 0, 0)
                Dim _date2 As New Date(DateTimePicker2.Value.Year, DateTimePicker2.Value.Month, DateTimePicker2.Value.Day, 23, 59, 59)
     
                Dim articles As New DataTable
                articles = db_centrale_foxpro.execute_select("select code,libelle,0.O,0.O,0.0,0.0,0.0 from article order by code asc")
     
                Dim ligne As DataRow = dernierInventaire()
                Dim code_inventaire As String = ligne.Item(0)
                Dim date_inventaire As Date = ligne.Item(1)
     
                Dim tampxls As New StringBuilder()
                tampxls.Append(vbTab).Append(vbTab).Append("MOUVEMENT DES ARTICLES   ").Append(vbTab).Append(vbTab).Append(vbTab).Append("Exporter Le:").Append(vbTab).Append(Date.Now()).Append(vbCr).Append(vbCr)
                tampxls.Append("Magasin :").Append(vbTab).Append(liste_depots.Text.ToString).Append(vbCr).Append(vbCr)
                tampxls.Append("Du").Append(vbTab).Append(DateTimePicker1.Value.Date.ToString).Append(vbTab).Append("A").Append(vbTab).Append(DateTimePicker2.Value.Date.ToString).Append(vbCr).Append(vbCr)
                tampxls.Append("code").Append(vbTab).Append("libelle").Append(vbTab).Append(vbTab).Append(vbTab).Append("QteInitial").Append(vbTab).Append("QteEntrer").Append(vbTab).Append("QteSortie").Append(vbTab).Append("CA").Append(vbTab).Append("StokFinal").Append(vbTab).Append(vbTab).Append(vbCr)
     
     
                For Each article As DataRow In articles.Rows
                    If article.Item(0).ToString.Trim <> "" Then
                        'qte initial
                        article.Item(2) = (qteInventaire(article.Item(0).ToString, code_inventaire) + qteInterDepot(article.Item(0).ToString, date_inventaire, _date1) + qteBonRetour(article.Item(0).ToString, date_inventaire, _date1)) - qteBonLivraison(article.Item(0).ToString, date_inventaire, _date1)
                        'qte entrer
                        article.Item(3) = qteInterDepot(article.Item(0).ToString, _date1, _date2) + qteBonRetour(article.Item(0).ToString, _date1, _date2)
                        'qte sortie
                        article.Item(4) = qteBonLivraison(article.Item(0).ToString, _date1, _date2)
                        'CA
                        article.Item(5) = chiffreAffaire(article.Item(0).ToString, _date1, _date2)
                        'stock final
                        article.Item(6) = (article.Item(2) + article.Item(3)) - article.Item(4)
     
     
                        tampxls.Append(article.Item(0).ToString).Append(vbTab)
                        tampxls.Append(article.Item(1).ToString).Append(vbTab).Append(vbTab).Append(vbTab)
                        tampxls.Append(article.Item(2).ToString).Append(vbTab)
                        tampxls.Append(article.Item(3).ToString).Append(vbTab)
                        tampxls.Append(article.Item(4).ToString).Append(vbTab)
                        tampxls.Append(article.Item(5).ToString).Append(vbTab)
                        tampxls.Append(article.Item(6).ToString).Append(vbTab).Append(vbCr)
     
                    End If
                Next
     
     
                tampxls.Append(vbCr).Append(vbTab).Append(vbTab).Append(vbTab).Append(vbTab).Append(vbTab).Append(vbTab).Append("TOTAL CA :").Append(vbTab).Append(vbTab).Append("0.0").Append(vbCr)
                tampxls.Append(vbCr).Append(vbTab).Append(vbTab).Append(vbTab).Append(vbTab).Append(vbTab).Append(vbTab).Append("TOTAL QteSortie :").Append(vbTab).Append(vbTab).Append("0.0").Append(vbCr)
                tampxls.Append(vbCr).Append(vbTab).Append(vbTab).Append(vbTab).Append(vbTab).Append(vbTab).Append(vbTab).Append("TOTAL QteEntrer :").Append(vbTab).Append(vbTab).Append("0.0").Append(vbCr)
     
     
                RichTextBox1.Text = tampxls.ToString()
                RichTextBox1.SaveFile("fichier.xls", RichTextBoxStreamType.PlainText)
            Catch ex As Exception
                MessageBox.Show(ex.Message, "ERREUR", MessageBoxButtons.OK, MessageBoxIcon.Error)
            End Try
        End Sub
    Voici un exemple d'une fonction parmi les fonctions que j'ai utilisé dans le traitement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Private Function qteBonLivraison(ByVal code_article As String, ByVal date1 As Date, ByVal date2 As Date) As Decimal
            Dim qte As Decimal
            Try
                qte = db_centrale_foxpro.valeurUnique("SELECT SUM(lblivre.qte) FROM lblivre WHERE lblivre.code='" & code_article & "' AND lblivre.nbl in (SELECT nbl FROM bonlivra WHERE bonlivra.depote=" & liste_depots.SelectedValue.ToString & " AND bonlivra.valide =.T. AND bonlivra.date BETWEEN " & General.toDateFoxPro(date1) & " AND " & General.toDateFoxPro(date2) & ")")
            Catch ex As Exception
                qte = 0
            End Try
            Return qte
        End Function
    Merci de votre aide ^^
    Images attachées Images attachées   

  2. #2
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 197
    Par défaut
    tu peux utiliser un chronomètre (system.diagnostics.stopwatch (.Start .Stop .ElapsedMillisecondes)) pour voir quelle partie du code est longue

    après on verra comment modifier le code qui est long
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  3. #3
    Modérateur
    Avatar de Sankasssss
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2006
    Messages
    1 842
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 842
    Par défaut
    Juste une petite remarque.
    Il est souvent possible de faire une énorme partie du travail directement dans la requête. Ca donne des requêtes énorme mais le temps de travail est drastiquement diminué.
    En héritant d'un projet d'un collègue qui devait exporter énormément de données provenant d'énormément de tables différentes, j'ai modifié son code qui faisait comme vous, c'est à dire que pour chaque ligne d'une première requête il exécutait une dizaine d'autre requête. J'ai tout mi dans une seul requête. Résultat, je suis passé d'un traitement de 4 heures à un traitement de 5 minutes !!!

    Déjà ici les deux requêtes que vous donnez pourrait déjà être rassemblées dans une seule.

    Autre piste d'amélioration, passer par un datareader au lieu d'un dataTable. Car il commence à traiter chaque ligne directement sans attendre d'avoir tout rapatrié en mémoir (ca prend du temps pour beaucoup de donnée) et ca rend le programme beaucoup moins gourmand en mémoire (il ne stocke qu'une ligne à la fois)

  4. #4
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 197
    Par défaut
    ah oui j'avais même pas fait gaffe qu'il y avait de la sous requete, il ne faut pas chercher plus loin

    les jointures (inner join et autres) permettent de faire des requetes sur plusieurs tables
    le sum nécessitera alors un group by en fin de requete

    pourquoi dans le 1er select mettre des 0.0, si la valeur est fixe, vous la connaissez, ca ne sert à rien de dire à la base de vous le rapatrier pour chaque ligne
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  5. #5
    Membre expérimenté Avatar de Saintelaitlait
    Homme Profil pro
    Responsable ServiceDesk
    Inscrit en
    Août 2011
    Messages
    179
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : Canada

    Informations professionnelles :
    Activité : Responsable ServiceDesk
    Secteur : Service public

    Informations forums :
    Inscription : Août 2011
    Messages : 179
    Par défaut
    Juste comme ca, sans améliorations de performances, mais améliorations de la lisibilité et de la stabilité.

    Pense à utiliser des requêtes paramètrées. Ca t'évitera de planter si une valeur que tu concatène contient un apostrophe.

    Et ce sera beaucoup plus facile à lire

    Plus d'infos ici
    http://webman.developpez.com/article...rameter/vbnet/

  6. #6
    Modérateur
    Avatar de Sankasssss
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2006
    Messages
    1 842
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 842
    Par défaut
    Citation Envoyé par Pol63 Voir le message
    les jointures (inner join et autres) permettent de faire des requetes sur plusieurs tables
    le sum nécessitera alors un group by en fin de requete
    Tout à fait, il y a aussi les sous-requêtes, les tables temporaires avec l'instruction With...

    Citation Envoyé par Pol63 Voir le message
    pourquoi dans le 1er select mettre des 0.0, si la valeur est fixe, vous la connaissez, ca ne sert à rien de dire à la base de vous le rapatrier pour chaque ligne
    C'est utilisé pour avoir des colonnes pour faire des calculs :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
                        'qte initial
                        article.Item(2) = (qteInventaire(article.Item(0).ToString, code_inventaire) + qteInterDepot(article.Item(0).ToString, date_inventaire, _date1) + qteBonRetour(article.Item(0).ToString, date_inventaire, _date1)) - qteBonLivraison(article.Item(0).ToString, date_inventaire, _date1)
                        'qte entrer
                        article.Item(3) = qteInterDepot(article.Item(0).ToString, _date1, _date2) + qteBonRetour(article.Item(0).ToString, _date1, _date2)
                        'qte sortie
                        article.Item(4) = qteBonLivraison(article.Item(0).ToString, _date1, _date2)
                        'CA
                        article.Item(5) = chiffreAffaire(article.Item(0).ToString, _date1, _date2)
                        'stock final
                        article.Item(6) = (article.Item(2) + article.Item(3)) - article.Item(4)
    Mais il est vrais que ce n'est pas du tout la bonne solution, sachant que toutes ces données vont transiter sur le réseau, et augmenté le temps de chargement du dataTable (Qu'il serait judicieux de remplacer par un DataReader pour préserver la mémoire et éviter le plantage)

    Il faudrait aussi, si ce n'est déjà fait, faire le traitement dans un thread séparé via par exemple un BackgroundWorker afin de ne pas figer l'application.

    zaghi va avoir du travail demain

  7. #7
    Expert confirmé Avatar de Graffito
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    5 993
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 993
    Par défaut
    j'ai un formulaire qui génère un fichier EXCEL
    Est-ce que le temps est significativement réduit si on n'opère pas les affectations aux cellules Excel ?

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

Discussions similaires

  1. Réponses: 7
    Dernier message: 03/05/2013, 20h15
  2. [MySQL] Optimisation d'un traitement arrêté par mon hébergeur
    Par lodan dans le forum PHP & Base de données
    Réponses: 17
    Dernier message: 27/02/2007, 20h37
  3. [Collection] Optimisation d'un traitement multithreads
    Par in dans le forum Collection et Stream
    Réponses: 6
    Dernier message: 30/11/2006, 10h28
  4. [C++/VB.Net]Optimiser des traitements lourds
    Par NiamorH dans le forum Windows Forms
    Réponses: 8
    Dernier message: 28/05/2006, 10h03
  5. [XSL] Optimisation d'un traitement de chaines de caractères
    Par mathieu dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 05/02/2006, 18h57

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