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

Bases de données Delphi Discussion :

Firedac,FMX Query asynchrone


Sujet :

Bases de données Delphi

  1. #1
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 569
    Billets dans le blog
    65
    Par défaut Firedac,FMX Query asynchrone
    Bonjour,

    je tente, sans trop de succès de comprendre comment faire une requête asynchrone (ResourceOptions.CmdExecMode:=TFDStanAsyncMode.amAsync)

    L'objectif remplir une listview d'une "grosse table". Visuellement le remplissage se fait en deux temps,pours les 50 premieres lignes c'est quasi instantané, ensuite (au lieu d'un SQLWait, que je pourrais caché) j'ai une animation. Problème cette animation se bloque quand même lors du second open d'où mon idée d'utiliser une requête asynchrone mais je ne trouve pas grand chose sur le sujet (à part l'exemple peu clair et que je n'ai jamais réussi à faire tourner


    j'étais parti sur un code de ce genre
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT ANNEE, NUMERO Orderid,LIV_VILLE shipName FROM FACTURES
    ORDER BY ANNEE,NUMERO
    &rowset

    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
    procedure TForm5.btnThreadClick(Sender: TObject);
    var n : Cardinal;
    begin
    Memo1.Lines.Clear;
    Orders.Active:=False;
    Orders.MacroByName('rowset').AsRaw:=' ROWS 50';
    n:=TThread.GetTickCount;
    Orders.ResourceOptions.CmdExecMode:=TFDStanAsyncMode.amBlocking;
    Orders.Active:=True;
    LinkListControlToField1.Active:=False;
    LinkListControlToField1.Active:=True;
    Memo1.Lines.Add('Temps tick '+(TThread.GetTickCount-n).ToString);
    TTask.Run(
     procedure
       var m : Cardinal;
           Topen : TThread;
       begin
        m:=TThread.GetTickCount;
        TThread.Synchronize(nil,
            procedure
            begin
              AniIndicator1.Visible:=True;
              AniIndicator1.Enabled:=True;
              Memo1.Lines.Add('Start Thread');
            end);
         Orders.DisableControls;
         Orders.Close;
    //     Orders.ResourceOptions.CmdExecMode:=TFDStanAsyncMode.amAsync;  // passage en mode asynchrone mais comment on sait que c'est fini ?
         Orders.MacroByName('rowset').Clear;
         Orders.Open();  // c'est là que ça coince
         TThread.Synchronize(nil,
            procedure
            begin
              Orders.EnableControls;
              AniIndicator1.Visible:=False;
              AniIndicator1.Enabled:=False;
              Memo1.Lines.Add('Fin Thread tick '+(TThread.GetTickCount-m).ToString);
            end);
        end
    );
    end;
    Seulement évidemment ça coince puisque je ne sais pas attendre la fin de l'ouverture de la requête.

    j'ai même tenté un truc comme ça
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    //     Orders.ResourceOptions.CmdExecMode:=TFDStanAsyncMode.amAsync;
         Orders.MacroByName('rowset').Clear;
         TOpen:=TThread.CreateAnonymousThread(
               procedure begin
                 Orders.Open();
               end);
         TOpen.Start;
         while not TOpen.CheckTerminated do sleep(1000);
    Mais là il me manque un truc et je n'ai pas fouillé.

  2. #2
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 569
    Billets dans le blog
    65
    Par défaut
    Sitôt posé je trouve que l'on peut tester l'état de la commande.

    csInactive A command is not prepared.
    csPrepared A command is prepared. A result set is not accessible.
    csExecuting A command execution is in progress.
    csOpen A command execution is finished. A result set is accessible and not yet fully fetched.
    csFetching A result set fetching is in progress.
    csAborting A command execution abortion is in progress.

    For example:

    FDQuery1.ResourceOptions.CmdExecMode := amAsync;
    FDQuery1.Open;
    while FDQuery1.Command.State = csExecuting do begin
    // do something while query is executing
    end;
    Sauf que, au sein de ma tâche, je ne vois pas comment m'y prendre
    Quelqu'un s''st-il déjà frotté à ce mode asynchrone?

  3. #3
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 001
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 001
    Par défaut
    Je ne connais pas FireDAC, en général, le DBGrid bénéficie d'un Fetch partiel (PackedRecord) de la Query (genre TOraQuery) qui delaye le temps d'affichage au moins d'un scroll volontaire
    Cela se complique avec un TListView si on le veut plein dès le début

    ça n'existe pas en FireDAC le fetch partiel ?
    ça doit être la valeur de FetchOptions.RecsMax et TFDFetchOptions.RowsetSize
    Je n'ai que les DCU de FireDac, j'espère que la version Architect fourni les sources car cela souvent a comprendre mieux que la doc

    Il n'y a pas un event genre OnDataAvailable ?
    AfterExecute quand le server SQL a terminé
    AfterGetRecords couplé avec RowsetSize, il doit y avoir un moyen pour obtenir un fetch asynchrone

    Sinon, le code en lambda, j'ai un peu de mal
    A Mon avis, tout ça est en trop, si FDQuery fourni un mode asynchrone c'est pour justement éviter de soi même lancer un thread et de gérer les verrous lectures\écritures
    J'ai fait des ouvertures de Open en asynchrone mais le Open rendait la même dès le début par contre fallait pas immédiatement lire de DataSet sinon ça petait

    J'utiliserais un OnIdle du TApplicationEvents
    D'ailleurs c'est durant le Idle de TApplication que cela dépile les Synchronize via CheckSynchronize

    Si avec un TDBGrid tu constates que FetchOptions.RowsetSize/RecsMax récupère bien les données par lot et qu'il faut faire défiler pour avoir la suite (la scrollbar grandi)
    Est-ce Open rend la main immédiatement avant d'avoir fait le Preprare, si oui, fait le Open dans le MainThread comme le premier

    je verrais bien deux animations différentes, une pour l'ouverture (un SQL complexe peut être long coté serveur, le ORDER BY par exemple nécessite une lecture des index si il y en a ou alors un parcours interne de la table avant de trouver le premier et calculer les suivants) et une pour la récupération de données

    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
    procedure TForm5.ApplicationEventsIdle(Sender: TObject; var Done: Boolean);
    begin
      if MilliSecondsBetween(FLastIdle, Now()) > 50 then // 50 a trouver la bonne fréquence pour cela fluide sans que cela consomme pas du CPU pour rien
      begin
        if FDQuery1.Command.State in [csPrepared, csExecuting, csOpen] then
        begin
          AniOpening.Visible:= True; // A vérifier si l'on change une propriété que cela la reset pas à Zéro
          AniOpening.Enabled := True; 
        end else
        begin
          AniOpening.Visible:= False;
          AniOpening.Enabled := False;
     
          AniFetching.Visible:= True; // A vérifier si l'on change une propriété que cela la reset pas à Zéro
          AniFetching.Enabled := True;
     
          if Orders.Command.State = csFetching  then
          begin  
             ... fonction qui rempli le TListView de façon incrémentale
          end
          else
          begin
            AniFetching.Visible:= False;
            AniFetching.Enabled := False;
          end;
        end;
     
        FLastIdle := Now();
      end;
    end;
    Si le Open prend du temps pour faire le SQL et donc ne rend pas la main immédiatement, lui tu le lance tout seul dans un Thread, tu laisses faire comme au dessus car a priori le Fetching peut être asynchrone, donc c'est que FireDAC assure les verrous de lecture\écriture sur les données tampon du DataSet et les données brutes issues du driver.

    Après si FetchOptions.RowsetSize/RecsMax ne fonctionne pas et que tu dois faire manuellement le "ROWS 50" et en boucle les "ROWS <m> TO <m+50>" , j'ai une autre vision où tu fais un objet TThreadedQuery qui en fait va créer un ou plusieurs objet TFDQuery (un pool de 2 à 5 objets) chaque s'occupant d'un lot d'enregistrement, il tourne chacun dans un thread séparé et alimente un tampon type TClientDataSet si à la fin tu souhaites avec un DataSet entier, lors de l'écriture du tampon celui est verrouillé le temps de copier le lot d'enregistrement et cela émet OnDataAvailable (soit juste le Delta attendu, soit le DataSet selon ton besoin final)

    évidemment, si par étrangeté cela réussi à récupère un lot avant un autre, cela met en attente les lots arrivés trop vite tant que le lot dans l'ordre prévu m..m+50 n'est pas arrivé


    Enfin note la valeur amNonBlocking ... on pourrait supposer que ton Open fait tout son taf entier jusqu'au premier fetch
    et dans l'implémentation de FireDAC, je devine des Application.ProcessMessages pour laisser tourner une animation
    Après reste la partie Fetch et l'option OnIdle qui lit 50 enregistrements toutes les n millisecondes, pas besoin de thread, c'est juste qu'au lieu de tout lire d'un coup, tu lis quand l'application n'a rien de mieux à faire (ce qui arrive très souvent entre deux paint/click)
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  4. #4
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 569
    Billets dans le blog
    65
    Par défaut
    Bonjour,
    Citation Envoyé par ShaiLeTroll Voir le message
    Je ne connais pas FireDAC, en général, le DBGrid bénéficie d'un Fetch partiel (PackedRecord) de la Query (genre TOraQuery) qui delaye le temps d'affichage au moins d'un scroll volontaire
    Pour les grilles pas de souci, il est dommage que TlistView n'ai pas le même comportement (c'est d'ailleurs déjà demandé sur le QC)

    Cela se complique avec un TListView si on le veut plein dès le début
    Le problème c'est bien le Tlistview qui ne bénificie pas du Fetch partiel

    ça n'existe pas en FireDAC le fetch partiel ?
    Bien sûr que si, et du coup je peux faire de la pagination sans problème cf https://www.developpez.net/forums/d2...s-suggestions/

    Je n'ai que les DCU de FireDac, j'espère que la version Architect fourni les sources car cela souvent a comprendre mieux que la doc
    à partir de la version entreprise. Je vais me pencher sur la partie qui gère le dialogue TFDStanAsyncMode.amCancelDialog

    Il n'y a pas un event genre OnDataAvailable ?
    AfterExecute quand le server SQL a terminé
    Pas pensé à ça

    A Mon avis, tout ça est en trop, si FDQuery fourni un mode asynchrone c'est pour justement éviter de soi même lancer un thread et de gérer les verrous lectures\écritures
    J'ai fait des ouvertures de Open en asynchrone mais le Open rendait la même dès le début par contre fallait pas immédiatement lire de DataSet sinon ça petait
    Que ce soit trop, je suis d'accord, en fait je suis parti de la constatation du délai (long 15-17 s) d'une ouverture "classique" et j'ai voulu voir comment je pourrais rendre l'ouverture plus "souple", d'où la tache, l'animation et mon questionnement. (Sans animation on ne se rend pas compte du blocage momentané).

    J'utiliserais un OnIdle du TApplicationEvents
    Encore une fois je n'y ai pas pensé.(j'ai toujours été frileux avec l'utilisation de OnIdle)
    Merci de cet exemple.
    if FDQuery1.Command.State in [csPrepared, csExecuting, csOpen] then même ce in je l'avais totalement zapper hier soir (fin de journée n'est pas bonne idée pour des essais). Je viens de faire l'essai dans mon code, j'en suis au même point : cela bloque l'animation.


    En autre idée je pourrais aussi utilisé deux querys différentes (l'une partielle RAW 50) et l'autre totale et changer le BindSourceDB.DataSet du lien (apparement mes divers comptage m'indique que la partie longue serait bien la récupération des données, pas le remplissage de la listview)

  5. #5
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 569
    Billets dans le blog
    65
    Par défaut
    Après diverses interventions "urgentes" et avant de me mettre à faire chauffer la ligne téléphonique pour des achats, j'ai pris le temps de tester ce dialogue TFDStanAsyncMode.amCancelDialog.

    Nom : Capture.PNG
Affichages : 953
Taille : 10,5 Ko
    Pas mal même si :
    - finalement, l'animation bloque tout pareil
    - et que, alors que tout est en français (et modifiable à volonté cf. FDGUIXAsyncExecuteDialog), le bouton du dialogue "Cancel" persiste en langue de Sheakeaspire dommage

  6. #6
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 912
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 912
    Par défaut
    Bonne année à tous

    Après amAsync/Open, ce serait l'événement OnAfterOpen. Delphi est livré avec un exemple de chargement asynchrone.

    Ensuite depuis un thread de travail, le mode devrait être au minimum sur amNonBlocking. Les erreurs que je mentionnais ici ont disparu dès que je l'ai changé.

    Mais ce qui n'est pas bon est l'accès aux mêmes composants (FDConnection/FDQuery) depuis deux threads différents. Tu devrais toi-même mettre en place une sérialisation des appels qui supprimeront tout l'intérêt du multithreading.

    Ce que j'essayerais plutôt est de créer dynamiquement les composants propres au thread de travail (FDConnection/FDQuery) et ne synchroniserais qu'un FDQuery.CopyDataSet en fin de chargement.

    Enfin une approche différente est de laisser le travail dans la tâche principale (puisque c'est pour de l'affichage) et de déporter l'animation dans un thread secondaire. C'est ce que j'avais fait avec l'unité WinXIndicator (qu'il faudra que je mette à jour...) en VCL.

  7. #7
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 001
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 001
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    B
    Pour les grilles pas de souci, il est dommage que TlistView n'ai pas le même comportement (c'est d'ailleurs déjà demandé sur le QC)

    Le problème c'est bien le Tlistview qui ne bénificie pas du Fetch partiel
    Tu rempli ce TListView FMX manuellement ou via Bindings
    Manuellement, tu aurais déjà toi même écrit je suppose un pagineur
    Bindings, là tu as ce problème mais je ne vois pas comment ça réagit avec Orders qui est ouvert\fermé\ouvert, il reste rempli même à la fermeture du DataSet ?
    FMX, je ne connais pas, alors je pose des questions bêtes

    Citation Envoyé par SergioMaster Voir le message
    - finalement, l'animation bloque tout pareil
    C'est le phase initiale avec le serveur SQL qui doit donc bloquer, un mode async avec gui non bloquant devrait on pourrait l'espérer lancer les taches bloquantes en thread
    15s pour un Open sur une table c'est très long mais FACTURES contient combien d'enregistrement ?
    Si tu ouvres le DataSet SANS aucun composant connecté dessus, c'est pareil ?
    En VCL, une grosse stat durait 11 minutes pour l'afficher entière dans une grille TMS avec Footer à totaux, le Open bloquait les 11 minutes
    Mais en réalité le Open durait "seulement" 4 minutes et le fetch en prenait 7, du coup un mode "rapide" a été ajouté avec une simple TDBGrid et si l'utilisateur voulait tout voir (genre exporter sur Excel) ou alors avoir des totaux, le fetch était complété jusqu'à la fin (avec de la pagination de ODAC)
    C'est la grille TMS pour alimenter son Footer qui dès le Open faisait un fetch complet totalement invisible qui donnait l'impression que le Open bloquait plus longtemps que nécessaire
    Alors comme les Bindings se comportent et peuvent ils parasiter le Open ?
    La requête sur la console du SBGD est aussi longue ?


    Je pense que le mode Bindings va a un moment donné nuire à ton effet progressif à moins de mettre un Animation.Refresh() dans le AfterGetRecords (voire AfterGetRecord) ça peut fluidifier la partie Fetch
    Je partirais sur un mode manuel
    après, c'est typiquement le genre de truc où l'on trouve la solution un peu à tâtons en observant le comportement de chaque élément
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  8. #8
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 569
    Billets dans le blog
    65
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    Tu remplis ce TListView FMX manuellement ou via Bindings
    Avec bindings (que ce soit en mode paginé ou non d'ailleurs)

    Bindings, là tu as ce problème mais je ne vois pas comment ça réagit avec Orders qui est ouvert\fermé\ouvert, il reste rempli même à la fermeture du DataSet ?
    un DisableControls permet de garder les 50 (dans mon exemple) premières lignes le temps que tout se charge, donc oui


    15s pour un Open sur une table c'est très long mais FACTURES contient combien d'enregistrement ?
    environ 185000 (j'aurais pu faire l'essai sur les lignes de factures mais ce n'est qu'un essai) dans une base sur le réseau local (connexion wifi histoire de rallonger les temps)

    Si tu ouvres le DataSet SANS aucun composant connecté dessus, c'est pareil ?
    temps ouverture 2.8

    Alors comme les Bindings se comportent et peuvent ils parasiter le Open ?
    c'est ce que je cherche à découvrir
    La requête sur la console du SBGD est aussi longue ?
    difficile de l'affirmer car le GUI que j'utilise lit les 300 premières lignes (environ 0.1 s max) mais ne chronométre pas le fetchAll

    Je pense que le mode Bindings va a un moment donné nuire à ton effet progressif à moins de mettre un Animation.Refresh() dans le AfterGetRecords (voire AfterGetRecord) ça peut fluidifier la partie Fetch
    le lien est désactivé le temps de l'ouverture, de plus il n'est pas en autoactivate, c'est ce code qui procéde au remplissage
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
           LinkListControlToField1.Active:=False;
           LinkListControlToField1.Active:=True;
    et c'est bien là l'objet de ma recherche : savoir le temps imputé à la récupération des données et celle au remplissage d'une TListView, savoir si ce dernier est optimisable (ajout de TlistView.BeginUpdate .EndUpate) et enfin détecter s'il n'y a pas là un problème d'algorithme (possible, car démontré pour un remplissage manuel dans une vidéo brésilienne qu'il va me falloir retrouver. Je me souviens de cette vidéo qu'un ajout d'un élement était mis au debut de la liste avant d'être descendu vers le bas item par item, facile de comprendre la lenteur dès qu'un nombre "raisonnable" est dépassé )


    Pour l'instant c'est du 40/60
    Citation Envoyé par memo
    Temps pour rows 50 0.328
    Start Thread
    End Open thread tick 2.813 (donc identique)
    End Update list thread tick 6.6
    Je partirais sur un mode manuel
    bien sûr c'est une solution mais pourquoi se priver des LiveBindings qui font les mêmes opérations ? De plus quel "temps" cela donnerait, je verrais ça demain


    c'est typiquement le genre de truc où l'on trouve la solution un peu à tâtons en observant le comportement de chaque élément
    Si j'otais l'animation aucune "secousse" ne serait visible

    Je suis d'accord et c'est bien pour cela que je me suis lancé dans cette recherche, la pagination fonctionne parfaitement mais j'aurais voulu exposer ces deux approches. Une animation sans à coup fait valeur de test. En fait Embarcadero ne me propose pas mieux avec le mode amCancelDialog, là aussi il y a "blocage" de l'animation

  9. #9
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 001
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 001
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    temps ouverture 2.8...

    difficile de l'affirmer car le GUI que j'utilise lit les 300 premières lignes (environ 0.1 s max) mais ne chronométre pas le fetchAll
    Déjà ça c'est pas top !
    Le Open d'un TFDQuery ne devrait pas mettre au temps si rien n'est connecté, on dirait que tu as un FetchAll dès le Open
    ce fetch partiel est vraiment actif ou pas ?
    car si le fetch partiel est actif et que cela met 2.8s pour récupérer quelques premières lignes contre 0.1s sur l'outil console, là déjà je ferais des essais avec ADO par exemple pour comparer
    On ne peut pas tolérer qu'un Open soit aussi peu performant lorsque l'on constate qu'ailleurs ça va plus vite
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  10. #10
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 569
    Billets dans le blog
    65
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    Déjà ça c'est pas top !
    non, on ne s'est pas compris, c'est le temps du fetchall sans liste liée

  11. #11
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 001
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 001
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    non, on ne s'est pas compris, c'est le temps du fetchall sans liste liée
    Ah, moi je ferais donc un Open en Fetch partiel, copie des 50 premiers, ensuite dans OnIdle, un Timer ou même un PostMessage si ça existe en FMX (ça je pratique souvent un WM_DELAYED = WM_USER + n), la récupération de la suite en plusieurs fois pour laisser le comportement normal de l'application (sans forcer une boucle à base de ProcessMessages);

    Après afficher une liste de 185000 me laisse perplexe, je préfère plutôt encourager un filtre pour réduire la quantité en dehors d'une Grille dotée d'un export Excel
    J'utiliserais deux requêtes SELECT COUNT + SELECT ROW (ou un seule si ça supporte "COUNT(*) OVER()") pour afficher la progression de récupération + une gérer une ScrollBar qui reflète la réalité (ou une ligne en fin de liste indiquant que c'est pas fini)
    Si l'utilisateur force le défilement (clavier, scrollbar ...), j'augmenterais donc le fenêtre de transfert DataSet->ListView et si il fait genre Cltr+Fin, là ben punition, une animation et on finit tout immédiatement
    Evidemment, si l'écran permet une recherche, le locate va fetcher, ça on laisse faire et une patience le temps du transfert DataSet->ListView jusqu'à la ligne choisie
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  12. #12
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 569
    Billets dans le blog
    65
    Par défaut
    Bonjour,
    Citation Envoyé par ShaiLeTroll Voir le message
    Ah, moi je ferais donc un Open en Fetch partiel, copie des 50 premiers,
    Cette partie ne me pose aucun problème
    Après afficher une liste de 185000 me laisse perplexe, je préfère plutôt encourager un filtre
    Je te rapelles que c'est un essai pour voir ce qu'il en est en temps de chargement, bien sûr que dans une application utilisateur je demande avant tout une Année ou un client ou .. (dans le cas de facture) pour réduire le nombre de lignes.
    J'ai déjà déduit
    - que 60% du temps environ était pour le remplissage de la liste (en cas de livebindings)
    - Que même le dialogue d'exécution Asynchrone de la requête bloque durant le remplissage de liste
    Conclusion possible, étrangemement, aucun thread n'est utilisé pour remplir le listview via LiveBindings (impossible de trouver où cela se fait dans les sources)

  13. #13
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 569
    Billets dans le blog
    65
    Par défaut
    Bonjour,

    j'ai enfin trouvé une solution qui me permet d'avoir l'animation durant le remplissage de la liste

    J'ai rajouté un variable idl, initialisée à 0 au début du remplissage puis fait appel à l'évènement onFillingListItem
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    procedure TForm5.LinkListControlToField1FillingListItem(Sender: TObject;
      const AEditor: IBindListEditorItem);
    begin
    inc(idl);
    if AniIndicator1.Visible AND (idl mod 1000=0) then Application.ProcessMessages;
    end;
    Bien que cet Application.ProcessMessages ne me plaise qu'à moitié et que le test sur le modulo est certainement à changer (fonction temps ?) il n'y a plus d'à coups perceptibles.
    ou presque

    N.B. je croyais faire les tests en réseau local en fait, non, ma connexion se faisait sur une base via internet, ce qui explique mieux les temps

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

Discussions similaires

  1. Query Begin et Commit son sur un bateau....
    Par faoz75 dans le forum Requêtes
    Réponses: 5
    Dernier message: 15/08/2003, 11h48
  2. Je ne retrouve pas ma SP dans Query analyser
    Par WOLO Laurent dans le forum MS SQL Server
    Réponses: 4
    Dernier message: 14/07/2003, 12h43
  3. Query data set
    Par Sandra dans le forum JBuilder
    Réponses: 3
    Dernier message: 20/01/2003, 10h08
  4. [XMLRAD] Décoder Request.Query
    Par Sylvain Leray dans le forum XMLRAD
    Réponses: 8
    Dernier message: 10/01/2003, 16h40
  5. Réponses: 6
    Dernier message: 25/03/2002, 21h11

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