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 :

Est-ce que le résultat d’une requête dépend de son plan d’exécution ?


Sujet :

SQL Oracle

  1. #1
    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 Est-ce que le résultat d’une requête dépend de son plan d’exécution ?
    Bien sûr que non!

    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
     
    Connecté à :
    Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bit Production
    With the Partitioning, OLAP, Data Mining and Real Application Testing options
     
    SQL> set linesize 132
    SQL> create index hr.emp_hire_date on hr.employees(hire_date)
    /
    Index créé.
     
    SQL> set autotrace on
    SQL> Select
           employee_id,
           first_name,
           salary
      From (
            Select employee_id,
                   first_name,
                   salary,
                   hire_date
              from hr.employees
            order by hire_date desc
    )
    where rownum = 1
    /
     
    EMPLOYEE_ID FIRST_NAME               SALARY
    ----------- -------------------- ----------
            173 Sundita                    6100
     
    Plan d'exécution
    ----------------------------------------------------------
    Plan hash value: 3645119196
     
    -----------------------------------------------------------------------------------------------
    | Id  | Operation                     | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
    -----------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT              |               |     1 |    38 |     2   (0)| 00:00:01 |
    |*  1 |  COUNT STOPKEY                |               |       |       |            |          |
    |   2 |   VIEW                        |               |     1 |    38 |     2   (0)| 00:00:01 |
    |   3 |    TABLE ACCESS BY INDEX ROWID| EMPLOYEES     |   107 |  2461 |     2   (0)| 00:00:01 |
    |   4 |     INDEX FULL SCAN DESCENDING| EMP_HIRE_DATE |     1 |       |     1   (0)| 00:00:01 |
    -----------------------------------------------------------------------------------------------
     
    Predicate Information (identified by operation id):
    ---------------------------------------------------
     
       1 - filter(ROWNUM=1)
    C'est Sundita!

    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
     
     Select --+ ALL_ROWS
           employee_id,
           first_name,
           salary
      From (
            Select employee_id,
                   first_name,
                   salary,
                   hire_date
              from hr.employees
            order by hire_date desc
           )
    where rownum = 1
    /
     
    EMPLOYEE_ID FIRST_NAME               SALARY
    ----------- -------------------- ----------
            167 Amit                       6200
     
    Plan d'exécution
    ----------------------------------------------------------
    Plan hash value: 3819624196
     
    -------------------------------------------------------------------------------------
    | Id  | Operation               | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
    -------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT        |           |     1 |    38 |     4  (25)| 00:00:01 |
    |*  1 |  COUNT STOPKEY          |           |       |       |            |          |
    |   2 |   VIEW                  |           |   107 |  4066 |     4  (25)| 00:00:01 |
    |*  3 |    SORT ORDER BY STOPKEY|           |   107 |  2461 |     4  (25)| 00:00:01 |
    |   4 |     TABLE ACCESS FULL   | EMPLOYEES |   107 |  2461 |     3   (0)| 00:00:01 |
    -------------------------------------------------------------------------------------
     
    Predicate Information (identified by operation id):
    ---------------------------------------------------
     
       1 - filter(ROWNUM=1)
       3 - filter(ROWNUM=1)
    Non c'est Amit!
    Non c’est Sundita !
    Non c’est Amit !

  2. #2
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Mars 2010
    Messages
    536
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 536
    Points : 1 359
    Points
    1 359
    Par défaut
    Citation Envoyé par mnitu Voir le message
    Bien sûr que non!

    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
     
    Connecté à :
    Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bit Production
    With the Partitioning, OLAP, Data Mining and Real Application Testing options
     
    SQL> set linesize 132
    SQL> create index hr.emp_hire_date on hr.employees(hire_date)
    /
    Index créé.
     
    SQL> set autotrace on
    SQL> Select
           employee_id,
           first_name,
           salary
      From (
            Select employee_id,
                   first_name,
                   salary,
                   hire_date
              from hr.employees
            order by hire_date desc
    )
    where rownum = 1
    /
     
    EMPLOYEE_ID FIRST_NAME               SALARY
    ----------- -------------------- ----------
            173 Sundita                    6100
     
    Plan d'exécution
    ----------------------------------------------------------
    Plan hash value: 3645119196
     
    -----------------------------------------------------------------------------------------------
    | Id  | Operation                     | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
    -----------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT              |               |     1 |    38 |     2   (0)| 00:00:01 |
    |*  1 |  COUNT STOPKEY                |               |       |       |            |          |
    |   2 |   VIEW                        |               |     1 |    38 |     2   (0)| 00:00:01 |
    |   3 |    TABLE ACCESS BY INDEX ROWID| EMPLOYEES     |   107 |  2461 |     2   (0)| 00:00:01 |
    |   4 |     INDEX FULL SCAN DESCENDING| EMP_HIRE_DATE |     1 |       |     1   (0)| 00:00:01 |
    -----------------------------------------------------------------------------------------------
     
    Predicate Information (identified by operation id):
    ---------------------------------------------------
     
       1 - filter(ROWNUM=1)
    C'est Sundita!

    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
     
     Select --+ ALL_ROWS
           employee_id,
           first_name,
           salary
      From (
            Select employee_id,
                   first_name,
                   salary,
                   hire_date
              from hr.employees
            order by hire_date desc
           )
    where rownum = 1
    /
     
    EMPLOYEE_ID FIRST_NAME               SALARY
    ----------- -------------------- ----------
            167 Amit                       6200
     
    Plan d'exécution
    ----------------------------------------------------------
    Plan hash value: 3819624196
     
    -------------------------------------------------------------------------------------
    | Id  | Operation               | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
    -------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT        |           |     1 |    38 |     4  (25)| 00:00:01 |
    |*  1 |  COUNT STOPKEY          |           |       |       |            |          |
    |   2 |   VIEW                  |           |   107 |  4066 |     4  (25)| 00:00:01 |
    |*  3 |    SORT ORDER BY STOPKEY|           |   107 |  2461 |     4  (25)| 00:00:01 |
    |   4 |     TABLE ACCESS FULL   | EMPLOYEES |   107 |  2461 |     3   (0)| 00:00:01 |
    -------------------------------------------------------------------------------------
     
    Predicate Information (identified by operation id):
    ---------------------------------------------------
     
       1 - filter(ROWNUM=1)
       3 - filter(ROWNUM=1)
    Non c'est Amit!
    Non c’est Sundita !
    Non c’est Amit !
    je vous l'ai dit : ROWNUM = 1 + ORDER BY = INDEX FULL SCAN = faire attention

    ROWNUM is not a fixed attribute of a specific row in a table – if you attempt to use it as such, you will not achieve the results that you are expecting

    Using ROWNUM in the Where Clause Causes Problems
    Bien Respectueusement
    www.hourim.wordpress.com

    "Ce qui se conçoit bien s'énonce clairement"

  3. #3
    Rédacteur

    Homme Profil pro
    Consultant / formateur Oracle et SQL Server
    Inscrit en
    Décembre 2002
    Messages
    3 460
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Consultant / formateur Oracle et SQL Server

    Informations forums :
    Inscription : Décembre 2002
    Messages : 3 460
    Points : 8 074
    Points
    8 074
    Par défaut
    La démonstration est intéressante, mais fonctionnellement, demander "sors-moi le dernier embauché" quand les dates d'embauche ne sont pas uniques, c'est déjà bancal.
    Consultant / formateur Oracle indépendant
    Certifié OCP 12c, 11g, 10g ; sécurité 11g

    Ma dernière formation Oracle 19c publiée sur Linkedin : https://fr.linkedin.com/learning/oracle-19c-l-administration

  4. #4
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 820
    Points
    17 820
    Par défaut
    Citation Envoyé par Mohamed.Houri Voir le message
    je vous l'ai dit : ROWNUM = 1 + ORDER BY = INDEX FULL SCAN = faire attention
    Finalement, on est revenu à l'époque du RULE !

  5. #5
    Expert éminent
    Avatar de pachot
    Homme Profil pro
    Developer Advocate YugabyteDB
    Inscrit en
    Novembre 2007
    Messages
    1 821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Suisse

    Informations professionnelles :
    Activité : Developer Advocate YugabyteDB
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2007
    Messages : 1 821
    Points : 6 443
    Points
    6 443
    Billets dans le blog
    1
    Par défaut
    Bonjour,

    Citation Envoyé par Mohamed.Houri Voir le message
    je vous l'ai dit : ROWNUM = 1 + ORDER BY = INDEX FULL SCAN = faire attention
    Attention à quoi ? INDEX FAST FULL SCAN est le moyen le plus rapide d'aller chercher la première (ou dernière) entrée d'un index. 'FULL SCAN' est un peu trompeur ici puisqu'on s'arrête à la première ligne.

    Sinon, mnitu, le résultat ne dépends pas que du plan d'exécution mais aussi de l'heure où on lance la requête parfois:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select current_timestamp from dual;
    Sans parler d'un order by dbms_random.value ... Il y a des tas de raisons d'avoir un résultat différent. Ce qui compte, c'est que chaque résultat réponde à la requête, et c'est le cas dans ton exemple 'sortir un un employé embauché à la date la plus récente'.

    Cordialement,
    Franck.
    Franck Pachot - Developer Advocate Yugabyte 🚀 Base de Données distribuée, open source, compatible PostgreSQL
    🗣 twitter: @FranckPachot - 📝 blog: blog.pachot.net - 🎧 podcast en français : https://anchor.fm/franckpachot

  6. #6
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Mars 2010
    Messages
    536
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 536
    Points : 1 359
    Points
    1 359
    Par défaut
    Citation Envoyé par pachot Voir le message
    Bonjour,


    Attention à quoi ? FAST FULL SCAN est le moyen le plus rapide d'aller chercher la première (ou dernière) entrée d'un index. 'FULL SCAN' est un peu trompeur ici puisqu'on s'arrête à la première ligne.

    Cordialement,
    Franck.
    Franck,

    Ce n'est pas le INDEX FAST FULL SCAN mais le INDEX FULL SCAN dont je parle ici. Il y a une différence entre les deux.

    De plus, je ne demande pas à faire attention à toute utilisation d'un INDEX FULL SCAN; mais uniquement à l'apparition de ce dernier lorsque plusieurs circonstances l'accompagnent. Entre autres, lorsque dans la requête qui l'utilise, il y a (a) un ORDER BY et (b) une clause du genre where ROWNUM <= 1

    Dans ce cas, le CBO passe en mode FIRST_ROWS et sous ce mode, le CBO préfère l'utilisation d'un INDEX FULL SCAN afin d'éviter un ORDER BY et ceci quelque soit le coup de l'opération INDEX FULL SCAN.

    Au passage, tu as peut-être bien remarqué la disparition de l'opération ORDER BY lorsque le INDEX FULL SCAN a été choisi par le CBO.

    J'ai essayé de simuler cet effet ici

    Order by and first_rows
    Bien Respectueusement
    www.hourim.wordpress.com

    "Ce qui se conçoit bien s'énonce clairement"

  7. #7
    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
    @Mohamed
    INDEX FULL SCAN ou INDEX FAST FULL SCAN aucun importance dans ce cas.

    @pachot
    Je ne connais pas beaucoup de monde qui s’attente à voir le même résultat sur une requête de type select timestamp … et avec dbms_random si on veut on pourrait s’arranger !

    @pomalaix
    Ce n’est pas demander "sors-moi le dernier embauché" quand les dates d'embauche ne sont pas uniques qui est bancal mais oublier que souvent, plusieurs enregistrements peuvent répondre à ce type de demande. Mais vous avez très bien pointé le vrai problème.

    Merci à tous de vos retours.

  8. #8
    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
    J'ai l'habitude de dire au client : ROWNUM = 1, c'est Oracle qui choisit la ligne
    More Code : More Bugs. Less Code : Less Bugs
    Mon Blog PL/Sql : Fichier Zip / Image BMP / Lire sqliteDB / QRCode et Images PNG ou BMP

  9. #9
    Expert éminent
    Avatar de pachot
    Homme Profil pro
    Developer Advocate YugabyteDB
    Inscrit en
    Novembre 2007
    Messages
    1 821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Suisse

    Informations professionnelles :
    Activité : Developer Advocate YugabyteDB
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2007
    Messages : 1 821
    Points : 6 443
    Points
    6 443
    Billets dans le blog
    1
    Par défaut
    Bonjour Mohamed,
    Ce n'est pas le INDEX FAST FULL SCAN mais le INDEX FULL SCAN dont je parle ici.
    Oui c'est un labsus. Je voulais dire 'INDEX FULL SCAN'. J'ai corrigé pour ne pas induire en erreur.
    Merci,
    Franck.
    Franck Pachot - Developer Advocate Yugabyte 🚀 Base de Données distribuée, open source, compatible PostgreSQL
    🗣 twitter: @FranckPachot - 📝 blog: blog.pachot.net - 🎧 podcast en français : https://anchor.fm/franckpachot

  10. #10
    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
    Citation Envoyé par pachot Voir le message
    Bonjour Mohamed,

    Oui c'est un labsus. ...
    Lapsus

Discussions similaires

  1. [AC-2003] enlever des 0 dans un champ de résultat d´une requête
    Par benPSA dans le forum Requêtes et SQL.
    Réponses: 3
    Dernier message: 22/10/2009, 13h08
  2. Réponses: 8
    Dernier message: 18/04/2008, 17h40
  3. récupérer le résultat d’une requête CMD
    Par horkets dans le forum VB.NET
    Réponses: 4
    Dernier message: 28/08/2007, 12h00
  4. Réponses: 5
    Dernier message: 08/03/2007, 12h14
  5. [MySQL] Est-ce que php supporte les requêtes imbriquées ?
    Par dahan dans le forum PHP & Base de données
    Réponses: 1
    Dernier message: 08/03/2006, 18h50

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