PC SOFT

FORUMS PROFESSIONNELS
WINDEVWEBDEV et WINDEV Mobile

Accueil → WINDEV 2024 → Plantage après quelques minutes : requête trop lourde ?
Plantage après quelques minutes : requête trop lourde ?
Débuté par DCAR, 18 juin 2017 13:37 - 15 réponses
Membre enregistré
7 messages
Posté le 18 juin 2017 - 13:37
Bonjour à tous,

J'ai exécute une requête qui retourne 157 colonnes et 700 000 lignes.
Je travaille avec SQLExec et SQLAvance.
Même si je ne fais aucun traitement dans ma boucle, lorsque la requête arrive à la 450 000ième ligne environ, le programme plante.
Si je joue la même requête avec 1 colonne alors j'arrive à terminer le traitement avec succès.

SQLPremier plante d'office (j'imagine pour la même cause).
SQLTable par 1 et par 1000 records également.

SGDBR : SQL Server 2016 Standard

Ma question est la suivante ; Je dois absolument retourner les 157 colonnes (grand-livre comptable) :
- Existe-t-il une solution pour permettre l'exécution et la lecture d'une requête comme celle-ci ?
=> J'imagine que d'autres développeurs doivent sortir des requêtes bien plus conséquentes dans leurs travaux.

Pas obligé de me donner un script mais une piste serait déjà génial ! ;-)

Un grand merci à tous et bon dimanche.

DCAR
Membre enregistré
2 566 messages
Popularité : +222 (260 votes)
Posté le 18 juin 2017 - 16:48
Bonjour,

Es-tu en 32 ou 64 bits ?

--
Cordialement,

Philippe SAINT-BERTIN
Géode Informatique
Membre enregistré
7 messages
Posté le 18 juin 2017 - 19:54
System 64 bits
SQL Server 64 bits
Windev 64 bits
Membre enregistré
177 messages
Popularité : +16 (16 votes)
Posté le 18 juin 2017 - 20:02
Bonjour,

Tu devrais plutôt ne lire que l'ID de l'enregistrement sur ta requête de 700 000 lignes et faire une autre requête qui retourne 1 seul enregistrement avec les 157 colonnes.

Bonne soirée.
jm
Membre enregistré
7 messages
Posté le 18 juin 2017 - 20:17
C'est pas top parce que je vais donc devoir jouer 700 000 requêtes, pas terrible en terme de performance :-(

--
Bien à vous,
Le DCAR
Membre enregistré
1 923 messages
Popularité : +53 (65 votes)
Posté le 18 juin 2017 - 20:58
Bonjour,

Alors 2 requêtes de 350 000...

--
Bon dev,
Jean-Pierre
Membre enregistré
2 566 messages
Popularité : +222 (260 votes)
Posté le 19 juin 2017 - 03:43
Bonjour,

As tu regardé la mémoire utilisée par ton appli au moment où elle plante ? As -tu un message d'erreur particulier ?

--
Cordialement,

Philippe SAINT-BERTIN
Géode Informatique
Membre enregistré
7 messages
Posté le 19 juin 2017 - 05:58
Ah voilà une bonne question ! Oui j'ai eu un souci de mémoire qui montait à 1,5 Go environ et ça crachait à ce moment là.

Mais entre deux, j'avais résolu le problème avec ceci dans ma boucle :
eHDL est un entier
SI SysVersionWindows(sysVersionPlateForme) = "NT" ALORS
eHDL = API("Kernel32","GetCurrentProcess")
API("psapi","EmptyWorkingSet",eHDL)
FIN


La mémoire ne monte plus (d'après ma lecture) mais le plantage survient toujours.

--
Bien à vous,
Le DCAR
Message modifié, 19 juin 2017 - 05:59
Membre enregistré
326 messages
Popularité : +15 (19 votes)
Posté le 19 juin 2017 - 09:38
Bonjour.
Où est le problème exactement : dans le programme Windev ou en amont ?
1 -> mise en cause de SQLServer : la requête en direct sur SQLServer fonctionne-t'elle ?
2a -> Si oui à question 1 : tester le driver ODBC : sous Excel version minimum 2010 vu ton nombre de lignes -> exécuter la requête : OK ?
Si OK à la 2a aller au point 3 sinon voir si les quelques paramétrages du driver influent ou pas. Voir la version du Driver .... si bien en 64 bits....
2b -> Si non à la question 1 : voir le paramétrage de SQLServer et utiliser le plan d’exécution, le tracer voir les index, les différents paramétrages.
3 -> Dans Windev ? Par contre je te déconseillerai le vidage de la mémoire en même temps que le traitement...

...

Je viens de relire ton post initial : à priori c'est la lecture qui pose souci. C'est certain tu dois saturer la mémoire ! Pour optimiser ton traitement et faire qu'il fonctionne il a la possibilité de faire une vue SQLServer là tu n'as ensuite qu'à lire cette vue. Sinon l'option la plus simple. : Tu ramènes tes données sur des périodes plus courtes: 12 requêtes mensuelles par exemple.

Courage.

Michel.

PS : au fait quel temps pour exécuter la requête totale sans lecture.
Membre enregistré
7 messages
Posté le 19 juin 2017 - 12:55
Salut Michel,

1 -> La requête en direct sur SQL Server fonctionne bien, je sors jusqu'à 13 000 000 de lignes quand je prends un exercice complet.
2a -> J'ai testé de sortir sur un fichier plat (type csv, TAB et txt) : le problème se pose de la même manière donc pas lié à Excel.
2b -> SQL Server retourne les résultats très rapidement donc pas de souci à ce niveau là.
=> D'ailleurs si je créé la requête sous forme de vue et que je fais un appel en direct depuis Excel vers SQL Server, cela fonctionne mais c'est pas ça que je cherche.
3 -> OK pour ne pas vider la mémoire, pas de souci pour moi, mais ça ne résoud pas le problème.

J'aime bien ta solution et je dis oui, mais le client ne veut pas. Il comprend pas que sur Dynamics (MS), cela fonctionnait très bien :-(

Merci pour l'aide en tout cas, sympa de prendre du temps pour moi !

PS : La requête renvoie les 700 000 lignes en 12 secondes.

--
Bien à vous,
Le DCAR
Message modifié, 19 juin 2017 - 12:57
Membre enregistré
2 566 messages
Popularité : +222 (260 votes)
Posté le 19 juin 2017 - 13:03
Comment sont stockées les données lues ? Dans une variable type tableau ou un objet table windev ?
Membre enregistré
7 messages
Posté le 19 juin 2017 - 18:21
Je fonctionne avec les deux :
- SQLTable par 1000 lignes que je stocke ensuite dans un tableau de chaine.
- Après fermeture de la requête, je boucle sur le tableau de chaine et j'écris dans un fichier.

Mais même si je ne fais rien du tout dans la boucle des résultats de la requête, ça plante.

--
Bien à vous,
Le DCAR
Message modifié, 19 juin 2017 - 18:22
Membre enregistré
2 566 messages
Popularité : +222 (260 votes)
Posté le 20 juin 2017 - 05:25
Peux-tu mettre un bout de code de l'exécution de la requête et de la lecture de celle-ci ?

Ne pourrais-tu pas dans ce cas précis utiliser un fichier temporaire en HF qui serait local au poste et qui serait supprimé après traitement ? Cela permettrait peut-être d'être moins gourmand en RAM. Il reste à mettre des jauges de progression car le traitement peut-être long et ça énerve de ne pas savoir où on en est...

UnFichier est une Description dede Fichier
UneRubrique est une Description dede Rubrique
Ecritures est une Source dede Données
nNumColonne est un entier
nNumConnexion est un entier

// Description du fichier de données "Ecritures"
UnFichier..Nom = "Ecritures"
UnFichier..Type = hFichierNormal
UnFichier..CryptageFic = hCryptageStandard

// Création du fichier de données Client (reconnu car déclaré comme source de données)
HCreation(Ecritures)

i est un entier = 0
SQLExec("SELECT COL1,COL2,COL3,...,COL157 FROM TABLE", "REQ1")

//description des rubriques
sColonnes est une chaîne = SQLColonne(nNumConnexion,"REQ1")
POUR TOUTE chaîne sUneColonne de sColonnes SEPAREE PAR RC
UneRubrique..Nom = ExtraitChaîne(sUneColonne,1)
SELON ExtraitChaîne(sUneColonne,3)
CAS 1: UneRubrique..Type = hRubBooléen
CAS 2: UneRubrique..Type = hRubEntier4
CAS 3: UneRubrique..Type = hRubEntier8
...
FIN
SI UneRubrique..Type DANS (hRubCaractère,hRubTexte,hRubTexteUnicode) ALORS UneRubrique..Taille = Val(ExtraitChaîne(sUneColonne,4))
HDécritRubrique(UnFichier, UneRubrique)
FIN
// Valide la description du fichier de données
HDécritFichier(UnFichier)


// Récupérer la requête ligne à ligne
TANTQUE SQLAvance("REQ1") = 0
// Il y a encore une ligne à lire
i++

// Récupérer les données
nNumColonne = 1
HRAZ(Ecritures)
POUR TOUTE chaîne sUneColonne de sColonnes
{"Ecritures."+ExtraitChaîne(sUneColonne,1),indRubrique} = SQLLitCol("REQ1",nNumColonne)
nNumColonne++
FIN
HAjoute(Ecritures)
FIN
SQLFerme("REQ1")


--
Cordialement,

Philippe SAINT-BERTIN
Géode Informatique
Membre enregistré
7 messages
Posté le 20 juin 2017 - 08:38
Je teste ça dans les deux jours et je reviens vers toi avec le résultat.

Ca fait plaisir d'avoir une piste parce qu'avant d'ouvrir ce poste, j'ai testé beaucoup de solutions moi-même et rien n'y fait.

Un grand merci Philippe ! :-)

--
Bien à vous,
Le DCAR
Membre enregistré
326 messages
Popularité : +15 (19 votes)
Posté le 20 juin 2017 - 12:05
Bonjour.
Je suis un peu pessimiste sur l'écriture d'un fichier HF -> les temps d'écritures et de lectures sur un disque dur (SSD pas essayé) ne sont pas comparables avec des temps de lectures et écritures en mémoire. De plus le Hajoute est bien plus lent que le HEcrit -> c'est ce que je ferai avec une réindexation à la fin.
Sinon une question : quel est l'objectif final d'avoir toutes ces lignes ? Éditions, sauvegarde, contrôle ???
Dans ma boite quand les commissaires aux comptes viennent ils demandent des extractions spécifiques selon leur axe de recherche. Une fois le FISC nous a demandé la base comptable mais sous forme de fichiers texte !

Michel
Membre enregistré
2 566 messages
Popularité : +222 (260 votes)
Posté le 20 juin 2017 - 12:14
Certes les temps d'écriture et de lecture ne sont pas comparables mais on limite la saturation mémoire, ce qui se produit apparemment pour le moment. Si la mémoire atteint les 1.5 Go à 400 000 lignes, en extrapolant, on n'est pas très loin des 3 Go juste pour monter les données. Sur le poste de M. tout le monde, ce n'est même pas envisageable.

Moi perso je n'ai pas de client qui prennent des postes avec 32 Go de RAM pour leur employés pour faire de l'administratif.

Ce que je donne n'est qu'une piste à explorer. Je n'assure pas que ce soit l'idéal ni que ce soit totalement fonctionnel.

--
Cordialement,

Philippe SAINT-BERTIN
Géode Informatique