Précédent   Forum des professionnels en informatique > Bases de données > Oracle > PL/SQL
PL/SQL Forum d'entraide sur le PL/SQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 19/04/2011, 10h27   #1
Invité régulier
 
Inscription : mars 2011
Messages : 48
Détails du profil
Informations forums :
Inscription : mars 2011
Messages : 48
Points : 7
Points : 7
Par défaut Requête qui dure longtemps sans résultat

Bonjour ,
j'ai une requête qui dure longtemps sans me retourner de résultat jusqu'à que j'arrête l'exécution de ma requête
Code :
1
2
3
4
5
6
 
SELECT count(sectionid_fk) 
FROM Sectionname  
WHERE sectionid_fk NOT IN (SELECT sectionid_fk 
                           FROM Sectionname@BDPROD ) 
GROUP BY sectionid_fk
comment je peux remédier à cela ??

Merci pour toute information
SALMHSN est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/04/2011, 13h23   #2
Membre chevronné
 
Homme O. Joly
Support
Inscription : décembre 2010
Messages : 287
Détails du profil
Informations personnelles :
Nom : Homme O. Joly
Âge : 38
Localisation : France, Seine et Marne (Île de France)

Informations professionnelles :
Activité : Support
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : décembre 2010
Messages : 287
Points : 617
Points : 617
C'est quoi longtemps ?
C'est quoi la taille (en nombre de blocs) des tables ?
Pourquoi un group by sur sectionid_fk ?

Pour ma part je créerais une table temporaire (ou une vue matérialisée)

Code :
1
2
CREATE global TEMPORARY TABLE tmp_sec_name
AS SELECT DISTINCT sectionid_fk FROM Sectionname@BDPROD ;
et ensuite je rééxécutarais sans group by et en utilisant ma table temporaire

Code :
1
2
3
4
SELECT count(sectionid_fk) 
FROM Sectionname  
WHERE sectionid_fk NOT IN (SELECT sectionid_fk 
                           FROM tmp_sec_name ) ;
ojo77 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/04/2011, 10h39   #3
Invité régulier
 
Inscription : mars 2011
Messages : 48
Détails du profil
Informations forums :
Inscription : mars 2011
Messages : 48
Points : 7
Points : 7
mercii

j'ai dit longtemps parce que ma requete dure plus que 5 minutes sans me retourner de résultat !!!
la taille en nombre de lignes de la table sectionname est 985 lignes

et même si je fais :

Code :
1
2
3
SELECT count(sectionid_fk) 
FROM Sectionname  
WHERE sectionid_fk NOT IN (SELECT DISTINCT sectionid_fk FROM Sectionname@BDPROD  ) ;
ma requete dure encore plus que 3 minutes sans resultat


à quoi sert la table temporaire dans ce cas ??


Merci encore une fois
SALMHSN est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/04/2011, 11h32   #4
Rédacteur/Modérateur
 
Avatar de orafrance
 
Inscription : janvier 2004
Messages : 15 861
Détails du profil
Informations personnelles :
Âge : 34

Informations forums :
Inscription : janvier 2004
Messages : 15 861
Points : 16 212
Points : 16 212
Y a-t-il un index sur la colonne sectionid_fk ?

Que donne :
Code :
1
2
3
SELECT count(sectionid_fk) 
FROM Sectionname  sn
WHERE NOT EXISTS (SELECT 1 FROM Sectionname@BDPROD WHERE sectionid_fk=sn.sectionid_fk );
Attention, sectionid_fk ne doit pas être nullable

Sinon, ce serait pas mal d'avoir les plans d'exécution aussi :neutre:

PS : supprime le DISTINCT qui n'a aucun intérêt si ce n'est de faire un tri inutile
orafrance est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/04/2011, 11h38   #5
Membre expérimenté
 
François
Inscription : février 2010
Messages : 305
Détails du profil
Informations personnelles :
Nom : François

Informations forums :
Inscription : février 2010
Messages : 305
Points : 535
Points : 535
Par défaut Savoir ou chercher

Pour ameliorer le temps d'execution, un truc qui est pratique, c'est de savoir precisement ou Oracle passe son temps.

Un tkprof ou un explain plan serait une bonne base pour voir ce qui va de travers.
Rams7s est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/04/2011, 11h38   #6
Rédacteur/Modérateur
 
Avatar de orafrance
 
Inscription : janvier 2004
Messages : 15 861
Détails du profil
Informations personnelles :
Âge : 34

Informations forums :
Inscription : janvier 2004
Messages : 15 861
Points : 16 212
Points : 16 212
Citation:
Envoyé par SALMHSN Voir le message
la taille en nombre de lignes de la table sectionname est 985 lignes
Dans les 2 bases ? Combien de temps dure :

Code :
1
2
SELECT count(sectionid_fk) 
FROM Sectionname
Et

Code :
1
2
SELECT count(sectionid_fk) 
FROM Sectionname@BDPROD
orafrance est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 20/04/2011, 13h34   #7
Membre chevronné
 
Homme O. Joly
Support
Inscription : décembre 2010
Messages : 287
Détails du profil
Informations personnelles :
Nom : Homme O. Joly
Âge : 38
Localisation : France, Seine et Marne (Île de France)

Informations professionnelles :
Activité : Support
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : décembre 2010
Messages : 287
Points : 617
Points : 617
Citation:
Envoyé par SALMHSN Voir le message
mercii

j'ai dit longtemps parce que ma requete dure plus que 5 minutes sans me retourner de résultat !!!
la taille en nombre de lignes de la table sectionname est 985 lignes

et même si je fais :

Code :
1
2
3
SELECT count(sectionid_fk) 
FROM Sectionname  
WHERE sectionid_fk NOT IN (SELECT DISTINCT sectionid_fk FROM Sectionname@BDPROD  ) ;
ma requete dure encore plus que 3 minutes sans resultat


à quoi sert la table temporaire dans ce cas ??


Merci encore une fois
Oui mais :
  • Ma question concernait le nombre de blocs (Oracle travaille avec des blocs pours ses jointures, pas avec des lignes)
  • L'amélioration principale que je vous proposais était d'utiliser une table temporaire intermédiaire (pour gagner sur cette fameuse jointure) et donc ne pas utiliser la table distante dans votre requête finale.
ojo77 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/04/2011, 13h49   #8
Rédacteur/Modérateur
 
Avatar de orafrance
 
Inscription : janvier 2004
Messages : 15 861
Détails du profil
Informations personnelles :
Âge : 34

Informations forums :
Inscription : janvier 2004
Messages : 15 861
Points : 16 212
Points : 16 212
Citation:
Envoyé par ojo77 Voir le message
L'amélioration principale que je vous proposais était d'utiliser une table temporaire intermédiaire (pour gagner sur cette fameuse jointure) et donc ne pas utiliser la table distante dans votre requête finale.
La requête ira surement plus vite mais le temps passé en moins dans la requête sera dépenser lors de la création de la table temporaire

Remplacer NOT IN par NOT EXIST devrait par contre permettre de réduire le nombre de lignes sélectionnées dans la base distante
orafrance est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 20/04/2011, 14h02   #9
Membre chevronné
 
Homme O. Joly
Support
Inscription : décembre 2010
Messages : 287
Détails du profil
Informations personnelles :
Nom : Homme O. Joly
Âge : 38
Localisation : France, Seine et Marne (Île de France)

Informations professionnelles :
Activité : Support
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : décembre 2010
Messages : 287
Points : 617
Points : 617
En fait remplacer le not in par un not exists est une amélioration, mais essentiellement parceque le plan d'exécution passe en HASH ANTI JOIN, par contre on garde le full scan.

Code :
1
2
3
4
SELECT count(HASH_VALUE)
FROM plan
WHERE HASH_VALUE NOT IN (SELECT HASH_VALUE FROM HVS )
/
Code :
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
SQL> set autotrace traceonly
SQL> /

EcoulÚ : 00 :00 :00.01

Plan d'exÚcution
----------------------------------------------------------
Plan hash value: 618421709

-----------------------------------------------------------------------------
| Id  | Operation            | Name | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |      |     1 |    13 |     7   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE      |      |     1 |    13 |            |          |
|*  2 |   FILTER             |      |       |       |            |          |
|   3 |    TABLE ACCESS FULL | PLAN |    83 |  1079 |     2   (0)| 00:00:01 |
|*  4 |    FILTER            |      |       |       |            |          |
|   5 |     TABLE ACCESS FULL| HVS  |     7 |       |     2   (0)| 00:00:01 |
-----------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter( NOT EXISTS (SELECT 0 FROM "HVS" "HVS" WHERE
              LNNVL(:B1<>:B2)))
   4 - filter(LNNVL(:B1<>:B2))

Note
-----
   - dynamic sampling used for this statement (level=2)


Statistiques
----------------------------------------------------------
          0  recursive calls
          0  db block gets
         25  consistent gets
          0  physical reads
          0  redo size
        440  bytes sent via SQL*Net to client
        420  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed
Code :
1
2
3
4
SELECT count(HASH_VALUE)
FROM plan
WHERE NOT EXISTS (SELECT 1 FROM HVS WHERE hvs.hv=plan.hash_value )
/
Code :
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
EcoulÚ : 00 :00 :00.00

Plan d'exÚcution
----------------------------------------------------------
Plan hash value: 3721283191

----------------------------------------------------------------------------
| Id  | Operation           | Name | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |      |     1 |    26 |     5  (20)| 00:00:01 |
|   1 |  SORT AGGREGATE     |      |     1 |    26 |            |          |
|*  2 |   HASH JOIN ANTI    |      |    83 |  2158 |     5  (20)| 00:00:01 |
|   3 |    TABLE ACCESS FULL| PLAN |    83 |  1079 |     2   (0)| 00:00:01 |
|   4 |    TABLE ACCESS FULL| HVS  |     7 |    91 |     2   (0)| 00:00:01 |
----------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("HVS"."HV"="PLAN"."HASH_VALUE")

Note
-----
   - dynamic sampling used for this statement (level=2)


Statistiques
----------------------------------------------------------
         32  recursive calls
          0  db block gets
         19  consistent gets
          0  physical reads
          0  redo size
        440  bytes sent via SQL*Net to client
        420  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed
MAIS on gagne bien 25% de gets (dans cet exemple) en écrivant la requête avec not exists.
ojo77 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/04/2011, 16h25   #10
Invité régulier
 
Inscription : mars 2011
Messages : 48
Détails du profil
Informations forums :
Inscription : mars 2011
Messages : 48
Points : 7
Points : 7
Bonjour les amis ,

je vous remercie infiniment pour votre soutien ainsi que votre intérêt

1- le count dans la base source dure 0.01 secondes ce qui est super
mais pour le count traité au niveau de la base distante
Code :
SELECT count(sectionid_fk) FROM sectionname@bdprod
il dure environ 11.16 secondes


2- pour le :
Code :
1
2
3
SELECT count(sectionid_fk) 
FROM Sectionname  sn
WHERE NOT EXISTS (SELECT 1 FROM Sectionname@BDPROD WHERE sectionid_fk=sn.sectionid_fk );
cette requete dure 32.43 secondes
3- oui il existe un index sur le foreign key sectionid_fk

maintenant est ce que je travaille avec la requête qui dure apparement 32.43 secondes ou quoi au juste ??

je vous remercie encore une fois pour votre intérêt
SALMHSN est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/04/2011, 17h45   #11
Membre chevronné
 
Homme O. Joly
Support
Inscription : décembre 2010
Messages : 287
Détails du profil
Informations personnelles :
Nom : Homme O. Joly
Âge : 38
Localisation : France, Seine et Marne (Île de France)

Informations professionnelles :
Activité : Support
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : décembre 2010
Messages : 287
Points : 617
Points : 617
Faut tester

Pour moi construire une vue matérialisée ou une table temporaire va durer 11 secondes et l'exécution de la requête (avec not exists sur la table temporaire) durera environ 2 centièmes, mais c'est à vérifier.
ojo77 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 29/04/2011, 18h14   #12
Nouveau Membre du Club
 
Inscription : septembre 2008
Messages : 77
Détails du profil
Informations forums :
Inscription : septembre 2008
Messages : 77
Points : 28
Points : 28
Bonjour,

je trouve que ce lien donne de bons conseils pour l'optimisation sous oracle http://jpg.developpez.com/oracle/tuning/
J'espère que ça va aider.
EAKOM est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 02/05/2011, 09h59   #13
McM
Expert Confirmé Sénior
 
Inscription : juillet 2003
Messages : 3 437
Détails du profil
Informations forums :
Inscription : juillet 2003
Messages : 3 437
Points : 4 173
Points : 4 173
Une astuce que j'ai trouvé pour faire des requêtes entre bases (lourdes mises à jour), utiliser des minus plutôt que des not exists.
Code :
1
2
3
4
5
SELECT COUNT(sectionid_fk) 
FROM Sectionname  
WHERE sectionid_fk IN (SELECT sectionid_fk FROM Sectionname  
                      MINUS
                      SELECT sectionid_fk FROM Sectionname@BDPROD)
__________________
More Code : More Bugs. Less Code : Less Bugs
McM est déconnecté   Envoyer un message privé Réponse avec citation 11
Vieux 03/05/2011, 12h04   #14
Membre Expert
 
Avatar de pacmann
 
Homme Pacman Pacman
Business analyst
Inscription : juin 2004
Messages : 1 417
Détails du profil
Informations personnelles :
Nom : Homme Pacman Pacman
Âge : 31
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : Business analyst
Secteur : Finance

Informations forums :
Inscription : juin 2004
Messages : 1 417
Points : 2 309
Points : 2 309
Salut !

J'ai quelques remarques / question :
- Attention, en enlevant le GROUP BY, on n'a pas le même résultat ! (Sauf si on ajoute DISTINCT dans le count ?)
=> Si c'est bien une FK, on peut avoit de multiples occurences pour une même valeur de FK...

- Euh un DB Link vers la PROD, c'est chaud un peu non ? (Question d'organisation de l'entreprise ensuite )
Ojo, d'accord pour ta remarque sur les blocs vs lignes... mais sur la requête qui chope juste les FK, dans la mesure où la colonne est indexée, on ne devrait pas mettre 11 secondes pour 1000 lignes !

D'où la question pour SALMHSN :
Je suppose qu'avec ta requête, tu essaies de voir les différences entre tes environnement de test ou dev et la prod... tu as besoin de faire ça souvent ? On ne te met pas à dispo des copies de PROD ?
__________________

(c'est ma photo)
Paku, Paku !
Pour les jeunes incultes : non, je ne suis pas un pokémon...

Le pacblog : http://pacmann.over-blog.com/
pacmann est déconnecté   Envoyer un message privé Réponse avec citation 10
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 06h32.


 
 
 
 
Partenaires

Hébergement Web