Molenn
Messages postés797Date d'inscriptionmardi 7 juin 2005StatutMembreDernière intervention23 février 2011
-
20 nov. 2006 à 12:21
Molenn
Messages postés797Date d'inscriptionmardi 7 juin 2005StatutMembreDernière intervention23 février 2011
-
20 nov. 2006 à 15:44
Bonjour,
J'ai un petit soucis d'optimisation d'une requête SQL, et je me dis que vous auriez peut être une idée à me proposer. Je n'ai pas trouvé mon bonheur dans le moteur de recherche, si sur les quelques sites WEb qui jusque là, m'avaient bien aidé à apprendre le SQL et le VBScript donc ...
Je vous expose vite fait mon cas :
Ce que je fais actuellement :
J'interroge une base de donnée située sur un réseau d'entreprise via un VBScript de cette forme :
Set objDBConnection = WScript.CreateObject("ADODB.Connection")
Set RS = WScript.CreateObject("ADODB.Recordset")
objDBConnection.open Blablablabla ...
SQL = "SELECT * FROM ... blablabla"
RS.open SQL,objDBConnection,1,1
Tout cela fonctionne nickel, mon soucis, c'est que entre la création de la requête et l'ouverture du recorset, pour me remonter une 20aine d'enregistrements, il se passe déjà 20 sec, ce qui est énorme pour une base de données ou tout le monde tape déjà allègrement, occasionnant sur l'appli en dépendant des temps de réponse pourris. Et comme mon script est appelé à tourner souvent.
Si je réduis mes critères de sélection, j'arrive à descendre à 3-4 s ce qui est déjà plus acceptable, mais j'ai 450 enregistrements.
Ma question :
Dans une requête faite sous ACCESS par exemple, je sais que je peux faire un SELECT * From Nom de table ou Nom de requête.
Est-ce que je peux en VBScript faire une interrogation d'un recordset ?
Je m'explique, si je crée un premier recordset "global" qui me remonte les 450 enregistrements "globaux", est-ce que je peux ouvrir un 2nd recorset avec une requête SQL qui va prendre pour table de données cette fois le contenu de mon 1er recordset ?
Est-ce que je suis sur une bonne piste ? Je suppose qu'une fois mon 1er recordset ouvert, les enregistrements sont chargés dans la mémoire de mon PC en local, donc, si je viens interroger ce recordset, je ne vais plus taper dans la base de données SQL Server sur le réseau ? Parce que ce n'est pas le temps de réponse à proprement parler qui me pose soucis, c'est le fait que ça vienne ralentir une base de données déjà "à risque" dans la boîte.
Si vous voyez d'autres possibilités, n'hésitez pas, mais je me doute que sans ma requête, vous ne pourrez pas m'en dire grand chose . J'ai plein de OR dans mes critères, et je n'ai pas de moyens de m'en passer (Les OR concerne des champs différents, pas seulement le contenu d'un seul champ).
cs_skweeky
Messages postés259Date d'inscriptionmercredi 3 mai 2006StatutMembreDernière intervention11 janvier 20108 20 nov. 2006 à 13:41
Bonjour,
Pour la première question, est ce l'on peut utiliser les données d'un RecordSet dans un second la réponse est oui, mais avec plus ou moins de facilité avec ADO... en recherchant sur Internet "Disconnected Recordset" "adLockBatchOptimistic" je pense qu'il facilement possible de trouver la méthode pour le faire (on déconnecte le RecordSet 1 ou le clone, etc.)
Pour les problèmes de performance il manque des éléments, il y 3 paramètres à prendre en compte :
CursorType = adOpenForwardOnly
LockType = adLockReadOnly ou adLockBatchOptimistic (pour le cas du RS déconnecté) CursorLocation = adUseClient
Qui sont 3 propriétés d'un RecordSet on fonction de la valeur des 3, l'emplacement des données peut changer... la manière d'interroger les données elle aussi, etc... Dans ce cas vous avez renseigné 1 et 1 ce qui correspond à KeySet et ReadOnly (le 3ème je ne sais pas)... Ce n'est pas la meilleure méthode d'accès le mieux étant ce que je mets ci dessus pour l'accès en lecrture seule. Pour des accès nécessitant des modification c'est un peu plus compliqué, l'aide sur ADO montre des exemples...
Molenn
Messages postés797Date d'inscriptionmardi 7 juin 2005StatutMembreDernière intervention23 février 20117 20 nov. 2006 à 15:44
D'abord, merci pour la réponse ... Je viens de passer une bonne heure à fouiller le net, et j'ai appris des tas de trucs , mais je ne vois pas comment l'appliquer à mon cas.
Effectivement, la possibilité de travailler avec un recordset déconnecté pourrait être intéressante pour moi, mais ce n'est pas le noeud de mon pb. En effet, que mon objet Recordset soit connecté ou non, je ne peux pas l'interroger pour créer un nouveau recordset.
Je suis ensuite parti sur les objets QueryDef (on peut créer des QueryDef temporaire) et TableDef (mais là, inutilisable : j ene veux surtout pas créer de nouvelles tables dans la base).
La méthode GetRow pourrait m'intéresser, je créer mon recordset et je sors tous les enregistrements dans un tableau qui est en quelque sorte, l'image à plat de mon recordset, et donc, quelque part, la "mini" base de données sur laquelle je veux travailler. Mais je ne vois pas comment faire l'équivalent de ma requête dedans, sauf à créer des boucles contrôlant chaque enregistrement du tableau. Mais bon, 5 boucles imbriquées pour vérifier un tableau qui fait 500 lignes sur 37 colonnes, je ne suis pas fan ^^
Je vais essayer d'illustrer plus précisément ce que je veux faire.
Table Clients
Ville Dpt Region Profession
Rennes 35 Bretagne Artisan
Lorient 56 Bretagne Ouvrier
Paris 75 Ile de France Artisan
Nantes 44 Pays de la Loire Artisan
Ma requête telle qu'elle est faite actuellement, correspondrait à :
Set objDBConnection = WScript.CreateObject("ADODB.Connection")
Set RS = WScript.CreateObject("ADODB.Recordset")
objDBConnection.open Blablablabla ...SQL "SELECT * FROM Clients WHERE ((Region 'Bretagne) OR (Dpt ='44') AND (Profession = 'Artisan'))"
RS.open SQL,objDBConnection,1,1
Ce qui fait donc que j'ai crée un recordset RS, qui contient les infos suivantes :
Rennes 35 Bretagne Artisan
Nantes 44 Pays de la Loire Artisan
C'est cette requête qui me prend 20 secondes.
Voici ce que j'aimerai réussir à faire :
Set objDBConnection = WScript.CreateObject("ADODB.Connection")
Set RS = WScript.CreateObject("ADODB.Recordset")
objDBConnection.open Blablablabla ...SQL "SELECT * FROM Clients WHERE (Profession 'Artisan')"
RS.open SQL,objDBConnection,1,1
Le Recordset RS crée contient
Rennes 35 Bretagne Artisan
Paris 75 Ile de France Artisan
Nantes 44 Pays de la Loire Artisan
Cette requête ne me prend que 3-4 secondes (ce qui est acceptable cette fois).
A ce niveau, je pourrais couper la connection pour être sûr de ne plus toucher à ma base de données, et je voudrais pouvoir ouvrir un recordset du type : SQL "SELECT * FROM RS WHERE ((Region 'Bretagne) OR (Dpt ='44'))"
RSBis.open SQL,objDBConnection,1,1
Là, à la rigueur, que ça prenne 10, 15 ou même 20 secondes, ça n'a aucune importance puisque je suis en local sur mon poste.
Crée un QueryDef me semblait une piste intéressante, pour remplacer mon RS. Mais si j'ai bien compris, un QueryDef, c'est juste une requête donc, les enregistrements ne sont pas inclus et si je l'interroge, en fait, je vais recrée ma requête entière et donc, je n'aurais rien gagné.
Je ne sais pas si je suis très clair en fait, je m'en rends compte
Sinon, et bien, il me restera la solution d'extraire ma requête initiale dans un fichier Excel ou une Base ACCESS et refaire tous mes tris derrière, mais je voudrais limiter au maximum les manips.