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 :

Différence d'exécution entre un max et un row_number [11g]


Sujet :

SQL Oracle

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre émérite Avatar de bstevy
    Homme Profil pro
    Solutions Architect
    Inscrit en
    Mai 2009
    Messages
    552
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : Japon

    Informations professionnelles :
    Activité : Solutions Architect
    Secteur : Finance

    Informations forums :
    Inscription : Mai 2009
    Messages : 552
    Par défaut Différence d'exécution entre un max et un row_number
    Bonjour,


    Je viens de m'essayer à une petite requète, j'ai testé de ramener mes lignes en utilisant une fonction max et une fonction row_number....
    mais je trouve que le temps d'exécution n'est pas du tout le même.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    select * from (
       select cv_con_number, 
              cv_number, 
              row_number() over (partition by cv_con_number order by cv_number desc) as FL_ROW, CV_STATUS_CODE
       from CONTRACT_VERSIONS
    ) where FL_ROW = 1
    --Environ 40 s

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    select * from (
       select cv_con_number, 
              cv_number, 
              max(cv_number) over (partition by cv_con_number) as max_cv_number, CV_STATUS_CODE
       from CONTRACT_VERSIONS
    ) where max_cv_number = cv_number
    --Environ 15 s


    Mes résultats sont identiques en terme de volumétrie. Mais j'aurais voulu avoir une explication sur le temps de traitement, est ce que l'une des fonctions est plus performante que l'autre, est ce que ca depend de la volumétrie, ou de certaines autres conditions ?

    C'est pas vraiment un problème que je pose, je voudrais juste savoir aupres des experts en architecture oracle s'ils ont un moyen d'expliquer cela pour ma culture générale

    Un grand merci d'avance à ceux qui se pencheront sur le sujet.






    Ha, et autre chose aussi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    select * 
    from CONTRACT_VERSIONS A
    where A.cv_number = (   select max(B.cv_number)
                            from CONTRACT_VERSIONS B 
                            where A.cv_con_number = B.cv_con_number
                            )
    Les fonctions analytiques ou cette jointure, lequel est le mieux en oracle ?

  2. #2
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 454
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 454
    Par défaut
    Il vous manque au moins deux solutions.

    1. FIRST / LAST :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
      select cv_con_number
           , max(cv_number)                                                      as cv_number
           , max(cv_status_code) keep (dense_rank first order by cv_number desc) as cv_status_code
        from contract_versions
    group by cv_con_number;
    2. Aggrégat simple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    With cte_max_con_number as
    (
      select cv_con_number
           , max(cv_number) as cv_number
        from contract_versions
    group by cv_con_number
    )
    select t1.cv_con_number
         , t1.cv_number
         , t1.cv_status_code
      from contract_versions  t1
      join cte_max_con_number t2
        on t2.cv_con_number = t1.cv_con_number
       and t2.cv_number     = t1.cv_number;
    Pour votre question, il n'y a pas de réponse magique.
    FIRST / LAST utilisent un SORT GROUP BY, qui est moins rapide qu'un HASH GROUP BY.
    La solution 2 ici doit faire plusieurs accès à la table.
    Les solutions analytiques doivent faire des tris, qui sont toujours coûteux.

    Ce que j'écris n'est pas une règle générale, mais plutôt des constats sur un environnement donné :
    • si vous avez beaucoup de colonnes, l'intérêt de FIRST / LAST s'amenuise
    • si vous avez beaucoup de lignes, l'intérêt des fonctions analytiques s'amenuise
    • la solution agrégée est la plus "scalable", et peut profiter d'un index
    • si vous avez très peu d’occurrences multiples par cv_con_number, il peut être rentable d'écrire la requête de cette façon :


    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
    With cte_contract_versions_mult as
    (
    select t1.cv_con_number
         , t1.cv_number
         , t1.cv_status_code
         , row_number() over (partition by t1.cv_con_number order by t1.cv_number desc) as fl_row
      from contract_versions t1
     where exists (select null
                     from contract_versions t2
                    where t2.cv_con_number = t1.cv_con_number
                      and t2.cv_number    <> t1.cv_number)
    )
    select cv_con_number
         , cv_number
         , cv_status_code
      from cte_contract_versions_mult
     where fl_row = 1
     union all
    select t1.cv_con_number
         , t1.cv_number
         , t1.cv_status_code
      from contract_versions t1
     where not exists (select null
                         from contract_versions t2
                        where t2.cv_con_number = t1.cv_con_number
                          and t2.cv_number    <> t1.cv_number);
    C'est une solution que j'ai déjà mise en place lorsque l'utilisation de row_number entraînait un tri de plusieurs millions de lignes alors que seules dix mille en avait besoin, j'ai divisé le temps d'exécution de la requête par 20.

    Mais encore une fois, chaque optimum de solution va dépendre du volume des données, de leur répartition, du serveur que vous avez derrière la requête.

  3. #3
    Membre émérite Avatar de bstevy
    Homme Profil pro
    Solutions Architect
    Inscrit en
    Mai 2009
    Messages
    552
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : Japon

    Informations professionnelles :
    Activité : Solutions Architect
    Secteur : Finance

    Informations forums :
    Inscription : Mai 2009
    Messages : 552
    Par défaut
    C'est super, je ne connaissais pas cette méthode first last. ^^
    Merci beaucoup, je suis toujours content d'apprendre des nouvelles facons de faire les choses !

    En fait, je viens d'arriver dans une équipe un peu "agée" et donc leur SQL date un petit peu. J'essaye donc d'optimiser leurs anciens codes car y'a moyen de diviser les temps de traitements au moins par deux. Faut surtout que je les empêche d'utiliser des curseurs à tout bout de champs !!!

    Mais je viens de Teradata donc j'ai pas encore les bons reflex oracle.


    En tout cas, merci beaucoup pour cette réponse et ces petits codes, ca m'est bien utile.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Différence d'exécution entre SQLPLUS 8 et 10
    Par bstevy dans le forum Sql*Plus
    Réponses: 1
    Dernier message: 23/01/2015, 12h53
  2. Différences à l'exécution entre la console et le web
    Par eldoir dans le forum SQL Procédural
    Réponses: 4
    Dernier message: 28/04/2014, 22h27
  3. Réponses: 2
    Dernier message: 16/08/2010, 00h43
  4. [SQL] Différence d'exécution d'une requête entre phpmyadmin et php
    Par lodan dans le forum PHP & Base de données
    Réponses: 4
    Dernier message: 31/08/2006, 15h56
  5. [Rave] Différence de langue entre exécution et design
    Par RamDevTeam dans le forum Composants VCL
    Réponses: 2
    Dernier message: 29/11/2005, 11h49

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