Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1629 connectés 

  FORUM HardWare.fr
  Programmation
  SQL/NoSQL

  [SQL] Temps d'execution d'une requete bizarre

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[SQL] Temps d'execution d'une requete bizarre

n°461429
-bigfoot-
Posté le 18-07-2003 à 12:18:07  profilanswer
 

Alors voila ma requete  

Code :
  1. SELECT
  2.   COUNT(v.log_id) as nbconnexion,
  3.   w.lb_utilisateur,
  4.   MAX(v.log_date) as dates
  5. FROM
  6.   v_mca_log_gold v,
  7.   vwcr_utilisateur w,
  8.   v_mca_securite s
  9. WHERE
  10.   s.cd_reseau in ('NGR1') and
  11.   upper(v.log_login) = upper (w.lb_login_nt) and
  12.   upper(v.log_login) = upper (s.login_nt)
  13. group by w.lb_utilisateur order by w.lb_utilisateur


 
Cette requete met 8 min 45 à s'exécuter  
 
alors que la requete suivante  
 

Code :
  1. SELECT
  2.   COUNT(v.log_id) as nbconnexion,
  3.   w.lb_utilisateur,
  4.   MAX(v.log_date) as dates
  5. FROM
  6.   v_mca_log_gold v,
  7.   vwcr_utilisateur w,
  8.   v_mca_securite s
  9. WHERE
  10.   upper(v.log_login) = upper (w.lb_login_nt) and
  11.   upper(v.log_login) = upper (s.login_nt)
  12. group by w.lb_utilisateur order by w.lb_utilisateur


 
Alors que cette requete met juste 2 secondes à s'exécuter
j'ai juste enlever la condition :

Code :
  1. s.cd_reseau in ('NGR1')

 
 
 
Quelqu'un a une idée pour améliorer le temps de réponse pour la première requete ??


Message édité par -bigfoot- le 18-07-2003 à 12:19:40
mood
Publicité
Posté le 18-07-2003 à 12:18:07  profilanswer
 

n°461435
hop le fou
Tu m'en diras tant
Posté le 18-07-2003 à 12:23:39  profilanswer
 

essaye s.cd_reseau = 'NGR1'
 
puisqu il n y a qu un élément
ca vient peut etre aussi d une table avec bcp bcp d'enregistrement et pas d index sur ton champ (mais avec un tps pareil je doute que ce soit ca qd meme...)

n°461447
polo021
Posté le 18-07-2003 à 12:31:14  profilanswer
 

sinon y a pas le mot cle "like"?

n°461457
-bigfoot-
Posté le 18-07-2003 à 12:43:36  profilanswer
 

Ma requete initial est sur plusieurs réseaux donc j'ai un "in"  
Mais sinon j'ai essayé avec un "=" avec un seul réseau et j'ai le même temps de réponse
 
Quand même bizarre ce problème  :pfff:  
sinon si ca se peut vous aider, le SGBD est Oracle


Message édité par -bigfoot- le 18-07-2003 à 12:44:26
n°461467
Agagax
Posté le 18-07-2003 à 12:59:30  profilanswer
 

:hello: explain plan est ton ami

n°461470
tomlameche
Et pourquoi pas ?
Posté le 18-07-2003 à 13:03:24  profilanswer
 

-BigFoot- a écrit :

Ma requete initial est sur plusieurs réseaux donc j'ai un "in"  
Mais sinon j'ai essayé avec un "=" avec un seul réseau et j'ai le même temps de réponse
 
Quand même bizarre ce problème  :pfff:  
sinon si ca se peut vous aider, le SGBD est Oracle


Sans doute qu'il n'y pas d'index sur ta colonne CD_RESEAU.
Essaie en créant un index sur les deux champs login_nt et cd_reseau de la table v_mcs_securite.
Si ca marche pas mieux je vois pas ...
Y a combien d'enregistrement dans tes tables ? T'as essayé de faire un explain plan pour voir si t'as pas un access full sur une grosse table ?


---------------
Gérez votre collection de BD en ligne ! ---- Electro-jazzy song ---- Dazie Mae - jazzy/bluesy/cabaret et plus si affinité
n°461509
-bigfoot-
Posté le 18-07-2003 à 13:32:09  profilanswer
 

Merci à tous pour vos réponses   :)  
 
Je vais essayer le explain plan (je ne sais pas comment l'utiliser mais je vais faire une petite recherche) et je vous tiens au courant  ;)

n°461710
-bigfoot-
Posté le 18-07-2003 à 15:56:15  profilanswer
 

Bon j'ai réussi à faire un explain plan mais maintenant j'ai besoin d'expert pour m'aider à le décrypter et savoir ce qu'il faut que je fasse pour optimiser mon code
 
En tout les cas, il est vraiment excellent ce forum, on a toujours de l'aide  :love:  :love:  
 
Bon voila l'image de ce que j'ai :  
 
http://bigtoof.free.fr/explain.jpg
 
 
Merci d'avance

n°461747
tomlameche
Et pourquoi pas ?
Posté le 18-07-2003 à 16:18:00  profilanswer
 

-BigFoot- a écrit :

Bon j'ai réussi à faire un explain plan mais maintenant j'ai besoin d'expert pour m'aider à le décrypter et savoir ce qu'il faut que je fasse pour optimiser mon code
 
En tout les cas, il est vraiment excellent ce forum, on a toujours de l'aide  :love:  :love:  
 
Bon voila l'image de ce que j'ai :  
 
http://bigtoof.free.fr/explain.jpg
 
 
Merci d'avance


Vu qu'il semble à l'image de ton post que tu utilise TOAD, le mieux est de l'utiliser !
Tu tape ta requete et tu fait CTRL+E et zou !
Enfin presque, faut juste définir la table d'explian plan dans les options. Donc dans le menu de TOAD : view>option> puis tu choisi Oracle et tu met le nom de ta table d'explain plan dans le bon champ ( certainement PLAN_TABLE ou un truc comme ça ).
Voilà.
Tu peux aussi regarder là : http://bai.skreel.org/?categorie=ora&offset=25


---------------
Gérez votre collection de BD en ligne ! ---- Electro-jazzy song ---- Dazie Mae - jazzy/bluesy/cabaret et plus si affinité
n°461770
-bigfoot-
Posté le 18-07-2003 à 16:35:34  profilanswer
 

oki merci pour l'info  :D  
sinon tu vois ce que je dois optimiser ?
 
Je vais essayer de créer un index sur le champ cd_reseau

mood
Publicité
Posté le 18-07-2003 à 16:35:34  profilanswer
 

n°462039
MagicBuzz
Posté le 18-07-2003 à 20:28:08  profilanswer
 

Poste les indexes de tes tables s'il te plait.
 
A tout les coups, s.cd_reseau n'est pas correctement indexé, et le mettre dans la requête provoque un nested loop sur un index contenant plus de champs que ceux filtrés.

n°462043
MagicBuzz
Posté le 18-07-2003 à 20:33:24  profilanswer
 

Sinon, réécrit la requête comme suit :
 

SELECT  
 COUNT(v.log_id) as nbconnexion,  
 w.lb_utilisateur,  
 MAX(v.log_date) as dates  
FROM  
 vwcr_utilisateur w,  
 v_mca_securite s,  
 v_mca_log_gold v  
WHERE  
 upper(s.login_nt) = upper (w.lb_login_nt) and    
 s.cd_reseau in ('NGR1') and
 upper(v.log_login) = upper (w.lb_login_nt)
group by w.lb_utilisateur order by w.lb_utilisateur


 
PS: j'ai rien changé au niveau de la requête, j'ai juste réarangé les champs pour qu'Oracle s'en sorte mieu au niveau des jointures (il va éviter de faire des doublons qu'ils faut ensuite filtrer) en réarangeant à la fois l'ordre des requêtes et en utilisant w.lb_login_nt pour les deux jointures, puisqu'à la base, je suppose que c'est un index unique, alors que s.login_nt semble contenir des doublons.


Message édité par MagicBuzz le 18-07-2003 à 20:39:07
n°462044
-bigfoot-
Posté le 18-07-2003 à 20:35:10  profilanswer
 

Je poste cela lundi car la je ne suis plus au taff  :D

n°462047
MagicBuzz
Posté le 18-07-2003 à 20:37:54  profilanswer
 

sorry, j'étais très occupé aujourd'hui :)
 
en fait, la modif sur la jointure devrait te faire gagner pas mal : tu devrais remplacer la série "sort, filter, nested loop hash join" par un "inner join" qui sera énormément plus rapide
ça devrais aussi te virer le "union-all"
 
sinon, vérifie que tes index uniques style "login" sont bien triés, à moins qu'ils soient souvent mis à jour.


Message édité par MagicBuzz le 18-07-2003 à 20:40:14
n°463043
-bigfoot-
Posté le 21-07-2003 à 09:13:47  profilanswer
 

Merci beaucoup MagicBuzz ;) , en utilisant ta requête dans le sens que tu m'as dis je passe de 8 min 45 sec à 2 sec.
Faudrait à l'avenir que je sache bien interpréter le résultat d'un explain

n°463174
MagicBuzz
Posté le 21-07-2003 à 11:32:38  profilanswer
 

Bah putain ! Ca c'est de l'optimisation :D
 
Même pas fait exprès, je pensais gagner seulement entre 20 et 30% :)

n°463222
-bigfoot-
Posté le 21-07-2003 à 12:36:06  profilanswer
 

C'est un record d'optimisation  :D

n°463358
MagicBuzz
Posté le 21-07-2003 à 14:08:28  profilanswer
 

Sinon, avant même d'interpréter le résultat de l'explain, il faut modéliser dans sa tête la base et la requête.
 
Grossomodo :
-> Faire les filtres les filtres et les jointures regroupés table par table.
-> Toujours faire les jointures avant les filtres (sauf pour la première, qui n'est pas fille d'une jointure)
-> Pour les jointures, réutiliser les tables qui contiennent le moins de données possibles, même si au niveau du modèle ça ne correspond pas aux relations qu'on a fait.
 
Exemple :
 
PROPRIETAIRE
----
UID
NOM
PRENOM
PERMIS_ID
 
 
ADRESSE
------
AID
NUMERO
RUE
VILLE
CP
PAYS
TYPE
PROPRIETAIRE_ID
 
VOITURE
-------
IMMATRICULATION
PROPRIETAIRE_ID
 
Maintenant, le problème est :
 
Retrouver l'adresse de résidence principaledu conducteur de la voiture immatriculée 1234AB56 (histoire de lui envoyer un PV par exemple)
 
Tu commences par le filtre le plus restrictif, donc ici, l'imatriculation, puisque c'est un identifiant (une ligne retournée)
 
where v.immatriculation = '1234AB56'
 
Ensuite, tu ne vas pas t'amuser à lier les utilisateurs aux adresses, sinon tu vas te retrouver avec un nombre incalculable de lignes - autant qu'il y a d'adresse dans la base -, qui devront être filtrées au moment de la jointure (perte de temps).  
 
Donc tu commences par retrouver le conducteur.
 
and p.uid = v.proprietaire_id
 
Puis, tu vas chercher les adresses du conducteur (NON, ne fait pas le filtre sur le type d'adresse AVANT, sinon tu vas filtrer les adresses habitation de TOUS les propriétaires. Donc à nouveau, trop de lignes. Tu vas donc chercher la liste des adresses du conducteur, qui représentent beaucoup moins de lignes.
 
and a.PROPRIETAIRE_ID = u.UID
 
Et enfin (et seulement maintenant) tu vas filtrer le type d'adresse.
 
and a.type = 'PRINCIPALE'
 
Ensuite, dans le FROM, il faut mettre les tables dans l'ordre inverse de leur position dans la requête.
 
Truc à bien garder en tête aussi :
 
and a.PROPRIETAIRE_ID = u.UID
 
est différent de  
 
and u.UID = a.PROPRIETAIRE_ID
 
En effet, le second va recherche tous les UID qui sont présents dans les adresses, et ensuite va filter pour retrouver les UID qui connerspondent aux précédents critères. Alors que le premier va rechercher les adresses qui correspondent uniquement aux prorpiétaires déjà filtrés.
 
Le requête est donc :
 
SELECT p.NOM, p.PRENOM, a.NUMERO, a.RUE, a.CP, a.VILLE, a.PAYS
FROM adresse a, proprietaire p, voiture v
WHERE v.immatriculation = '1234AB56'
AND p.uid = v.proprietaire_id
AND a.PROPRIETAIRE_ID = u.UID
AND a.type = 'PRINCIPALE'
 
Et non pas un truc monstrueux genre :
 
SELECT p.NOM, p.PRENOM, a.NUMERO, a.RUE, a.CP, a.VILLE, a.PAYS
FROM proprietaire p, voiture v, adresse a
WHERE a.PROPRIETAIRE_ID = v.PROPRIETAIRE_ID
AND a.PROPRIETAIRE = p.UID
AND a.TYPE = 'PRINCIPALE'
and v.IMMATRICULATION = '1234AB56'
 
La seconde est tout ce qu'il y a de plus immonde :D
... mais elle fonctionne aussi (c'est bien ça le problème...)


Message édité par MagicBuzz le 21-07-2003 à 14:12:11

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  SQL/NoSQL

  [SQL] Temps d'execution d'une requete bizarre

 

Sujets relatifs
[SQL] requete (optimisation toute simple help!!!!)Access requête sur reception du focus
Table SQL de pays[SQL] qlq connait comment récupérer le jour de la semaine?
[SQL] Requete qui compte un maximum...Temps de transfert Base Access ...SQL serveur
Plus de sujets relatifs à : [SQL] Temps d'execution d'une requete bizarre


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR