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

PL/SQL Oracle Discussion :

Requête qui dure longtemps sans résultat


Sujet :

PL/SQL Oracle

  1. #1
    Nouveau membre du Club
    Inscrit en
    Mars 2011
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : Mars 2011
    Messages : 49
    Points : 32
    Points
    32
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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

  2. #2
    Membre expérimenté Avatar de ojo77
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Décembre 2010
    Messages
    680
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte de base de données
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Décembre 2010
    Messages : 680
    Points : 1 597
    Points
    1 597
    Par défaut
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT count(sectionid_fk) 
    FROM Sectionname  
    WHERE sectionid_fk NOT IN (SELECT sectionid_fk 
                               FROM tmp_sec_name ) ;

  3. #3
    Nouveau membre du Club
    Inscrit en
    Mars 2011
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : Mars 2011
    Messages : 49
    Points : 32
    Points
    32
    Par défaut
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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

  4. #4
    Expert éminent sénior
    Avatar de orafrance
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    15 967
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Points : 19 075
    Points
    19 075
    Par défaut
    Y a-t-il un index sur la colonne sectionid_fk ?

    Que donne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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

  5. #5
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2010
    Messages
    412
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 412
    Points : 807
    Points
    807
    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.

  6. #6
    Expert éminent sénior
    Avatar de orafrance
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    15 967
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Points : 19 075
    Points
    19 075
    Par défaut
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SELECT count(sectionid_fk) 
    FROM Sectionname
    Et

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SELECT count(sectionid_fk) 
    FROM Sectionname@BDPROD

  7. #7
    Membre expérimenté Avatar de ojo77
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Décembre 2010
    Messages
    680
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte de base de données
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Décembre 2010
    Messages : 680
    Points : 1 597
    Points
    1 597
    Par défaut
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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.

  8. #8
    Expert éminent sénior
    Avatar de orafrance
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    15 967
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Points : 19 075
    Points
    19 075
    Par défaut
    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

  9. #9
    Membre expérimenté Avatar de ojo77
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Décembre 2010
    Messages
    680
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte de base de données
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Décembre 2010
    Messages : 680
    Points : 1 597
    Points
    1 597
    Par défaut
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    select count(HASH_VALUE)
    from plan
    where HASH_VALUE not in (select HASH_VALUE from HVS )
    /
    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
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    select count(HASH_VALUE)
    from plan
    where not exists (select 1 from HVS where hvs.hv=plan.hash_value )
    /
    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
    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.

  10. #10
    Nouveau membre du Club
    Inscrit en
    Mars 2011
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : Mars 2011
    Messages : 49
    Points : 32
    Points
    32
    Par défaut
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    select count(sectionid_fk) from sectionname@bdprod
    il dure environ 11.16 secondes


    2- pour le :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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

  11. #11
    Membre expérimenté Avatar de ojo77
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Décembre 2010
    Messages
    680
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte de base de données
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Décembre 2010
    Messages : 680
    Points : 1 597
    Points
    1 597
    Par défaut
    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.

  12. #12
    Membre du Club
    Inscrit en
    Septembre 2008
    Messages
    77
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 77
    Points : 59
    Points
    59
    Par défaut
    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.

  13. #13
    McM
    McM est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Points : 7 740
    Points
    7 740
    Billets dans le blog
    4
    Par défaut
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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)

  14. #14
    Membre émérite Avatar de pacmann
    Homme Profil pro
    Consulté Oracle
    Inscrit en
    Juin 2004
    Messages
    1 626
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Consulté Oracle
    Secteur : Distribution

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 626
    Points : 2 845
    Points
    2 845
    Par défaut
    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 ?

Discussions similaires

  1. Réponses: 8
    Dernier message: 04/06/2010, 15h50
  2. Réponses: 6
    Dernier message: 15/09/2009, 11h18
  3. Réponses: 23
    Dernier message: 31/05/2007, 16h09
  4. Requête access exécutée mais sans résultat
    Par gids01 dans le forum Windows Forms
    Réponses: 4
    Dernier message: 28/02/2007, 09h33
  5. [MySQL] Requête SUBSTRING et CHAR_LENGTH sans résultat
    Par Anduriel dans le forum PHP & Base de données
    Réponses: 4
    Dernier message: 25/08/2006, 12h50

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