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

PyQt Python Discussion :

optimiser l'accès à une BDD SQLITE [QtSql]


Sujet :

PyQt Python

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 49
    Points : 51
    Points
    51
    Par défaut optimiser l'accès à une BDD SQLITE
    salut à tous,

    Voici le contexte : avec python 3 et pyqt4, je demande à mon petit script d'accéder une BDD SQLITE3, de réaliser des calculs et de remplacer les valeurs dans les champs de la BDD.
    J'ai écrit une première version en utilisant des QSqlQueryModel, ça fonctionne correctement mais c'est un peu long et du coup l'affichage est gelé, l'utilisateur doit attendre la fin du traitement. A chaque itération de la boucle while, je mets à jour les données de la BDD en préparation de l'opération suivante, ce qui je pense ajoute du temps de traitement.
    voici le code avec qsqlquerymodel
    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
     
                        while index <= 12:    
                            print("***calcul total crédit***")
                            TotalCredit = self.CalculTotal("credit", index, anneeTraitee)
                            print("total crédit du mois {}/{} : {}".format(index, anneeTraitee, TotalCredit))
     
                            print("***calcul total débit***")            
                            TotalDebit = self.CalculTotal("debit", index, anneeTraitee)
                            print("total débit du mois {}/{} : {}".format(index, anneeTraitee, TotalDebit))
                            print("***calcul solde***")            
                            SoldeMois = Decimal(TotalCredit - TotalDebit).quantize(Decimal('1.00'))
                            print("Solde du mois {}/{} : {}".format(index,anneeTraitee, SoldeMois))
                            #MAJ les tables credit débit et solde
                            query = QSqlQueryModel()
                            query.setQuery("UPDATE CreditParMois SET Total = {} WHERE NMois = {} AND Annee = {}".format(TotalCredit, index, anneeTraitee))
                            if query.lastError().isValid():
                                QMessageBox.warning(self,"requete TotalCredit",query.lastError().text())
     
                            query.setQuery("UPDATE DebitParMois SET Total = {} WHERE NMois = {} AND Annee = {}".format(TotalDebit, index, anneeTraitee))
                            if query.lastError().isValid():
                                QMessageBox.warning(self,"requete TotalDebit",query.lastError().text())
     
                            query.setQuery("UPDATE SoldeParMois SET Total = {} WHERE NMois = {} AND Annee = {}".format(SoldeMois, index, anneeTraitee))
                            if query.lastError().isValid():
                                QMessageBox.warning(self,"requete SoldeMois",query.lastError().text())
     
                            #MAJ du solde à nouveau du mois suivant
                            #teste si le poste existe pour le mois suivant
                            #si mois = 12 teste si le poste existe pour le mois de janvier de l'année suivante
                            if index == 12: #permet les MAJ bilan pour le mois de décembre (ne passe qu'une fois dans la boucle)
                                MoisSuivant = 1
                                anneeTraitee = anneeTraitee + 1
                            else:
                                MoisSuivant = index+1
     
                            print("*** MAJ solde à nouveau {}/{} ***".format(MoisSuivant, anneeTraitee))
                            if MoisSuivant <= 12:
                                if MoisSuivant >= 10:
                                    filtre ="date >= '{}-{}-01' AND date <= '{}-{}-31'".format(anneeTraitee, MoisSuivant,anneeTraitee, MoisSuivant)
                                else:
                                    filtre ="date >= '{}-0{}-01' AND date <= '{}-0{}-31'".format(anneeTraitee, MoisSuivant, anneeTraitee, MoisSuivant)
     
                                query.setQuery("UPDATE Operations SET Montant = {} WHERE IDPoste = '13' AND {}".format(SoldeMois, filtre))
                                if query.lastError().isValid():
                                    QMessageBox.warning(self,"Erreur MAJ solde à nouveau pour {}/{}".format(MoisSuivant,anneeTraitee),query.lastError().text())
                                else:
                                    #print("MAJ solde à nouveau du mois {} ok !".format(MoisSuivant))
                                    #il faut remettre à jour la BDD à chaque fois
                                    QSqlDatabase.database().commit()
                                    self.completed = True
                                    self.emit(SIGNAL("afficheTotaux(bool)"),self.completed)
                            index = index + 1

    Même en mettant le code dans un thread à part, ça reste lent, ça m'étonne un peu mais bon.
    Donc du coup je me suis dit que peut-être en utilisant un QSqlTableModel ça fonctionnerait plus vite car la BDD ne serait mise à jour qu'à la fin de tous les traitements.

    ce qui donne ce code

    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
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
             while index <= 12:    
                            TotalCredit = self.CalculTotal("credit", index, anneeTraitee)
                            print("total crédit du mois {}/{} : {}".format(index, anneeTraitee, TotalCredit))
     
                            TotalDebit = self.CalculTotal("debit", index, anneeTraitee)
                            print("total débit du mois {}/{} : {}".format(index, anneeTraitee, TotalDebit))
     
                            SoldeMois = Decimal(TotalCredit - TotalDebit).quantize(Decimal('1.00'))
                            print("Solde du mois {}/{} : {}".format(index,anneeTraitee, SoldeMois))
     
                            #MAJ les tables credit débit et solde
                            #défini le filtre pour les modèles
                            filtre = "NMois = {} AND Annee = {}".format(index, anneeTraitee)
                            print(filtre)
                            modelCreditParMois.setFilter(filtre)
                            modelDebitParMois.setFilter(filtre)
                            modelSoldeParMois.setFilter(filtre)
     
                            modelCreditParMois.select() #rempli les tables
                            modelDebitParMois.select()
                            modelSoldeParMois.select()
     
                            print("ligne credit = {}".format(modelCreditParMois.rowCount(QModelIndex()))) #ne devrait remonter qu'une seule ligne correspondant à un mois d'une année
                            print("ligne debit = {}".format(modelDebitParMois.rowCount(QModelIndex())))
                            print("ligne solde = {}".format(modelSoldeParMois.rowCount(QModelIndex())))                        
     
                            creditRecord = modelCreditParMois.record(0) #grace au filtre le modele ne doit contenir qu'un seul enregistrement
                            debitRecord = modelDebitParMois.record(0)
                            soldeRecord = modelSoldeParMois.record(0)
     
                            if creditRecord.isEmpty() == False:
                                print("valeur avant modif = {}".format(creditRecord.value(3))) #valeur du champs Total
                                creditRecord.setValue(3, TotalCredit)
                                print("{}".format(creditRecord.value(3)))
                            else:
                                print("record vide !")
     
                            if debitRecord.isEmpty() == False:
                                print("valeur avant modif = {}".format(debitRecord.value(3)))
                                debitRecord.setValue(3, TotalDebit)
                            else:
                                print("record vide !")
     
                            if soldeRecord.isEmpty() == False:
                                print("valeur avant modif = {}".format(soldeRecord.value(3)))
                                soldeRecord.setValue(3, SoldeMois)
                            else:
                                print("record vide !")
     
     
                            #MAJ du solde à nouveau du mois suivant
                            #teste si le poste existe pour le mois suivant
                            #si mois = 12 teste si le poste existe pour le mois de janvier de l'année suivante
                            if index == 12: #permet les MAJ bilan pour le mois de décembre (ne passe qu'une fois dans la boucle)
                                MoisSuivant = 1
                                anneeTraitee = anneeTraitee + 1
                            else:
                                MoisSuivant = index+1
     
                            print("*** MAJ solde à nouveau {}/{} ***".format(MoisSuivant, anneeTraitee))
                            if MoisSuivant <= 12:
                                if MoisSuivant >= 10:
                                    filtreOp ="IDPoste = '13' AND date >= '{}-{}-01' AND date <= '{}-{}-31'".format(anneeTraitee, MoisSuivant,anneeTraitee, MoisSuivant)
                                else:
                                    filtreOp ="IDPoste = '13' AND date >= '{}-0{}-01' AND date <= '{}-0{}-31'".format(anneeTraitee, MoisSuivant, anneeTraitee, MoisSuivant)
     
                                modelOperation.setFilter(filtreOp)
                                modelOperation.select()
                                op = modelOperation.record(0)
     
                                if op.isEmpty() == False:
                                    op.setValue(6, SoldeMois) #montant du solde à nouveau du mois suivant = SoldeMois
                                else:
                                    print("record vide !")
     
                            #il faut mettre à jour les tables de la BDD
                            modelCreditParMois.submitAll()
                            modelDebitParMois.submitAll()
                            modelSoldeParMois.submitAll()
                            modelOperation.submitAll()
                            self.completed = True
                            self.emit(SIGNAL("afficheTotaux(bool)"),self.completed)
                            index = index + 1
    et là, c'est le drame, après application du filtre et du select, je n'arrive même pas à récupérer des valeurs, à priori je ne récupère rien, mes record sont égaux à None. Si quelqu'un a une idée, je preneur; peut-être avec un data/setdata ?
    l'autre point où j'aimerai un/des avis concerne l'utilisation de qsqlquerymodel ou de qsqltablemodel en termes de temps d'accès à une BDD, y-en-a-t-il un plus rapide que l'autre ?
    j'espère avoir été assez clair
    merci d'avance et bonne soirée
    Nico

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Salut,

    Citation Envoyé par nicolassar Voir le message
    Même en mettant le code dans un thread à part, ça reste lent, ça m'étonne un peu mais bon.
    Il faudrait déjà "mesurer" le temps pris par cette mise à jour avec SQlite "seul". Avec l'interface graphique, çà ne pourra pas aller plus vite sauf à essayez d'optimiser les requêtes, les tables,... Et çà vous permettra de savoir s'il faut plutôt travailler côté GUI ou côté base de données.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 49
    Points : 51
    Points
    51
    Par défaut
    salut, merci pour ton idée.
    je pensais qu'en utilisant les threads et des signaux dédiés, je pouvais séparer la partie gestion de l'affichage dans le thread principal et la partie traitement de données dans un thread à part qui tournerait en "arrière plan" sans geler ou ralentir l'affichage.

    peut-être que ça reste lent parce que les 2 threads accèdent en même temps à la même BDD, ça vient peut-être de là. Je n'ai pas utilisé de verrou. Le Thread principal affiche les données à partir d'un qsqltablemodel donc, si j'ai bien compris le principe, les données de la BDD sont chargées en mémoire dans le model. Si je ne fais que de l'affichage sans modification, le thread n'a pas besoin d'accéder à la BDD.

    ce week-end, j'essaierai de ne lancer que le thread de traitement de données pour estimer son temps de traitement.
    Nico

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 49
    Points : 51
    Points
    51
    Par défaut
    ça a été plus long que prévu mais j'ai quand même réussi à "comparer" les temps de traitement de QSqlQureyModel et de QSQlTableModel. A l'oeil nu, il n'y a pas photo QSqlTableModel est nettement plus rapide.
    L'affiche est gelé moins longtemps. Ce n'est pas la solution idéale mais c'est suffisant pour le moment.
    L'idéal étant, à mon avis, de séparer la gestion de l'affichage et celle de la base de données dans des processus différents, mais il faut que je refonde complètement mon appli.
    bon WE

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

Discussions similaires

  1. Conception de classes d'accès à une BDD
    Par uGhz dans le forum PHP & Base de données
    Réponses: 1
    Dernier message: 15/07/2008, 17h15
  2. [Visual Web Dev] Gérer l'accès à une BdD MySQL
    Par sanackas dans le forum ASP
    Réponses: 0
    Dernier message: 22/03/2008, 17h59
  3. acces à une bdd 2003
    Par patqc dans le forum Modélisation
    Réponses: 7
    Dernier message: 21/01/2008, 11h42
  4. VB2005 Accès à une bdd access avec un loginform
    Par Herlece dans le forum Windows Forms
    Réponses: 6
    Dernier message: 06/01/2008, 16h50

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