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

SQL Oracle Discussion :

[9i] Not in ou not exists


Sujet :

SQL Oracle

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 20
    Points : 8
    Points
    8
    Par défaut Not in ou not exists
    Bonjour,
    j'ai une requête SQL avec une sous-requête imbriquée par un prédicat not in qui est extrémement longue (plusieurs heures).
    J'ai modifié cette requête SQL pour utiliser le prédicat not exists et le temps d'exécution a a baissé considérablement.
    Pourriez-vous m'expliquer la différence entre ces 2 prédicats ?

    Merci d'avance.

    PS : Je suis sur une base Oracle version 9i.

  2. #2
    Membre habitué
    Inscrit en
    Juin 2003
    Messages
    107
    Détails du profil
    Informations forums :
    Inscription : Juin 2003
    Messages : 107
    Points : 126
    Points
    126
    Par défaut
    Oui pour nous aussi, c'est conseillé d'utiliser NOT EXISTS au lieu de NOT IN (temps d'exécution).

    En fait, parmi les raisons c’est que l’utilisation de NOT IN empêche Oracle d'utiliser les indexs existants.

  3. #3
    Rédacteur
    Avatar de Bruno2r
    Homme Profil pro
    Exploitation des données
    Inscrit en
    Décembre 2006
    Messages
    2 566
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Exploitation des données
    Secteur : Santé

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 566
    Points : 4 780
    Points
    4 780
    Par défaut ça existe
    Bonsoir,
    Je trouve logique qu'il soit plus rapide de vérifier au travers d'une équijointure que chaque valeur de A est trouvée ou pas (en utilisant effectivement l'index dès qu'il existe)
    plutôt que ramener la liste de toutes les valeurs de B au travers de la clause IN (SELECT ....)
    puis de parcourir cete liste (non indexée)
    pour vérifier chaque valeur de la table A en est absente
    (d'autant que par définition il faut parcourir toutes les valeurs de la liste B pour chaque valeur de A avant de savoir ... qu'elle ne s'y trouve pas !)

  4. #4
    Membre actif
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    178
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 178
    Points : 220
    Points
    220
    Par défaut
    Nous avons fait le même constat : NOT EXISTS est généralement beaucoup plus rapide.

    De plus, j'utilise désormais EXISTS au lieu de IN car je me suis fait piéger une fois par le fait que la valeur que je cherchais apparaissait bien dans le SELECT que j'avais dans le IN, mais comme le SELECT retournait une valeur NULL parmi d'autres valeurs non NULL, je ne récupérait pas mon enregistrement !

    Dès qu'une valeur NULL apparait dans une clause IN, celle-ci renvoie faux, ce qui est certainement dû au fait que rien n'est égal à NULL, mais c'est un peu déroutant !

    rbaraer

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    115
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 115
    Points : 53
    Points
    53
    Par défaut
    Pour la différence entre NOT EXISTE et NOT IN,je trouve NOT EXISTE qui renvoie un valeur false ou true,s'il satisfait la clause where,il va donner un résultat direct,mais NOT IN qu'il dois toutes les tuple et vérifient s'il correspond la condition ou non,donc si votre table est long,il va éxecuter long,si votre table est simple,il va faire vite.

  6. #6
    Expert éminent sénior Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Points : 11 252
    Points
    11 252
    Par défaut
    A une époque on disait que si la table extérieure contient beaucoup des enregisterements et la table intérieure avait peu, le "In" peut être plus performant dans le cas contraire c'est le "Exists" qui l'est. Mais voila les résultats sur une base Oracle 10

    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
    46
    47
    48
     
    select count(*)
      from big
     where object_id not in ( select object_id from small )
     
    call     count       cpu    elapsed       disk      query    current        rows
    ------- ------  -------- ---------- ---------- ---------- ----------  ----------
    Parse        1      0.00       0.03          0          0          0           0
    Execute      1      0.00       0.00          0          0          0           0
    Fetch        2      0.29       0.30          0        890          0           1
    ------- ------  -------- ---------- ---------- ---------- ----------  ----------
    total        4      0.29       0.33          0        890          0           1
     
    Misses in library cache during parse: 1
    Optimizer mode: ALL_ROWS
    Parsing user id: 62  
     
    Rows     Row Source Operation
    -------  ---------------------------------------------------
          1  SORT AGGREGATE (cr=890 pr=0 pw=0 time=301969 us)
     397840   HASH JOIN RIGHT ANTI (cr=890 pr=0 pw=0 time=1594361 us)
         99    INDEX FULL SCAN SMALL_IDX (cr=1 pr=0 pw=0 time=631 us)(object id 52939)
     398632    INDEX FAST FULL SCAN BIG_IDX (cr=889 pr=0 pw=0 time=1594608 us)(object id 52937)
     
    ********************************************************************************
     
    select count(*)
      from big
     where not exists ( select null from small where small.object_id = big.object_id )
     
    call     count       cpu    elapsed       disk      query    current        rows
    ------- ------  -------- ---------- ---------- ---------- ----------  ----------
    Parse        1      0.00       0.00          0          0          0           0
    Execute      1      0.00       0.00          0          0          0           0
    Fetch        2      0.29       0.30          0        890          0           1
    ------- ------  -------- ---------- ---------- ---------- ----------  ----------
    total        4      0.29       0.30          0        890          0           1
     
    Misses in library cache during parse: 1
    Optimizer mode: ALL_ROWS
    Parsing user id: 62  
     
    Rows     Row Source Operation
    -------  ---------------------------------------------------
          1  SORT AGGREGATE (cr=890 pr=0 pw=0 time=305323 us)
     397840   HASH JOIN RIGHT ANTI (cr=890 pr=0 pw=0 time=1992169 us)
         99    INDEX FULL SCAN SMALL_IDX (cr=1 pr=0 pw=0 time=529 us)(object id 52939)
     398632    INDEX FAST FULL SCAN BIG_IDX (cr=889 pr=0 pw=0 time=1594607 us)(object id 52937)
    donc même temps d'exécution ce qui n'est guerre étonant parce que les plans d'exécution sont idéntiques.

    Pour rbaraer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
     select ename, job, mgr
     from emp
     where empno in (null, 7844, 7876);
     
    ENAME      JOB              MGR
    ---------- --------- ----------
    TURNER     SALESMAN        7698
    ADAMS      CLERK           7788
    Probablement que t'a voulut dire NOT IN

  7. #7
    Membre actif
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Février 2005
    Messages
    250
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Eure (Haute Normandie)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Février 2005
    Messages : 250
    Points : 277
    Points
    277
    Par défaut
    Normalement les performances sont identiques entre les deux (Oracle en 9i ou plus récent arrive à savoir qu'il s'agit de la même requête)...

    Si tu as joué tes deux requêtes l'une après l'autre, la deuxième a sans doute été plus rapide car une partie des données était déjà en mémoire...

  8. #8
    Membre averti

    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 418
    Points : 328
    Points
    328
    Par défaut
    Bonjour à tous. Je profite de la discussion pour poser une petite question à mnitu
    Citation Envoyé par mnitu
    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
    SELECT count(*)
      FROM big
     WHERE object_id NOT IN ( SELECT object_id FROM small )
     
    call     count       cpu    elapsed       disk      query    current        rows
    ------- ------  -------- ---------- ---------- ---------- ----------  ----------
    Parse        1      0.00       0.03          0          0          0           0
    Execute      1      0.00       0.00          0          0          0           0
    Fetch        2      0.29       0.30          0        890          0           1
    ------- ------  -------- ---------- ---------- ---------- ----------  ----------
    total        4      0.29       0.33          0        890          0           1
     
    Misses IN library cache during parse: 1
    Optimizer mode: ALL_ROWS
    Parsing user id: 62  
     
    Rows     Row Source Operation
    -------  ---------------------------------------------------
          1  SORT AGGREGATE (cr=890 pr=0 pw=0 time=301969 us)
     397840   HASH JOIN RIGHT ANTI (cr=890 pr=0 pw=0 time=1594361 us)
         99    INDEX FULL SCAN SMALL_IDX (cr=1 pr=0 pw=0 time=631 us)(object id 52939)
     398632    INDEX FAST FULL SCAN BIG_IDX (cr=889 pr=0 pw=0 time=1594608 us)(object id 52937)
    Comment faire pour obtenir ces informations sur l'exécution d'une requête ? Je commence à tâter de l'EXPLAIN PLAN (set autotrace on sous sqlplus), mais je n'obtiens pas toutes ces infos.

  9. #9
    Expert éminent sénior Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Points : 11 252
    Points
    11 252
    Par défaut
    Pour marchand_de_sable
    Toutes les informations sont ici http://oracle.developpez.com/guide/tuning/tkprof/

  10. #10
    Membre averti

    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 418
    Points : 328
    Points
    328
    Par défaut
    Citation Envoyé par mnitu
    Pour marchand_de_sable
    Toutes les informations sont ici http://oracle.developpez.com/guide/tuning/tkprof/
    Merci pour le lien

Discussions similaires

  1. DELETE et NOT LIKE ou NOT EXISTS
    Par Le gris dans le forum Requêtes
    Réponses: 1
    Dernier message: 07/10/2013, 14h15
  2. [MySQL] Requête sur table de jointure avec not in ou not exists
    Par GueloSuperStar dans le forum Langage SQL
    Réponses: 12
    Dernier message: 08/03/2013, 15h01
  3. NOT IN et NOT EXISTS
    Par rsc dans le forum SQL
    Réponses: 10
    Dernier message: 20/09/2012, 08h06
  4. remplacer NOT IN par NOT EXISTS
    Par Louisa2005 dans le forum SQL
    Réponses: 5
    Dernier message: 25/03/2010, 10h04
  5. NOT IN et NOT EXISTS TRES long
    Par jdonet dans le forum Langage SQL
    Réponses: 5
    Dernier message: 23/09/2009, 18h10

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