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 :

Requête paramétrisée plus lente que requête non paramétrisée


Sujet :

SQL Oracle

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Rédacteur
    Avatar de Greybird
    Inscrit en
    Juin 2002
    Messages
    673
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 673
    Par défaut Requête paramétrisée plus lente que requête non paramétrisée
    Bonjour,

    Je travaille sur Oracle 10.2.0.4.

    Je rencontre aujourd'hui un souci qui me laisse perplexe, et je me tourne vers vous en quête d'une explication : une certaine requête non paramétrisée est extrèmement plus rapide que la même requête paramétrisée à laquelle on aurait passé les mêmes valeurs en paramètres. (1 seconde vs 1 minute)

    Ci dessous les requêtes et leur plan d'exécution.
    Code Requête paramétrisée : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    SELECT   *
        FROM TTABLE
       WHERE 0 = 0
         AND dateSaisie >= :dateSaisie
         AND type = :type
    ORDER BY idt DESC;
    Code Plan d'exécution : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    Operation                                Object Name     Rows     Bytes     Cost
     
    SELECT STATEMENT Optimizer Mode=CHOOSE                    458               5611
      SORT ORDER BY                                           458       631 K   5611
        TABLE ACCESS BY INDEX ROWID     BDD$OWNER.TTABLE      458       631 K   5092
          INDEX RANGE SCAN     BDD$OWNER.ITTABLE3             8 K                 27

    Code Requête non paramétrisée : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    SELECT   *
        FROM TTABLE
       WHERE 0 = 0
         AND dateSaisie >= TO_DATE('03/09/2011 00:00:00', 'MM/DD/YYYY HH24:MI:SS')
         AND type = 'TYPE'
    ORDER BY idt DESC;
    Code Plan d'exécution : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    Operation                                Object Name     Rows     Bytes     Cost
     
    SELECT STATEMENT Optimizer Mode=CHOOSE                      1                  5
      SORT ORDER BY                                             1       1 K        5
        TABLE ACCESS BY INDEX ROWID     BDD$OWNER.TTABLE        1       1 K        4
          INDEX RANGE SCAN     BDD$OWNER.ITTABLE3               1                  3

    S'agissant finalement du même plan, comment les coûts peuvent-il être aussi différents (moindre optimisation dans le cas de la requête paramétrisée du fait d'une moindre information ?) ?
    Et surtout, pourquoi une telle différence de temps d'exécution au final ? Avez-vous des pistes pour résoudre ce souci ?

    Merci d'avance,

    Arnaud

  2. #2
    Expert confirmé
    Avatar de pachot
    Homme Profil pro
    Developer Advocate YugabyteDB
    Inscrit en
    Novembre 2007
    Messages
    1 822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : Suisse

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

    Informations forums :
    Inscription : Novembre 2007
    Messages : 1 822
    Billets dans le blog
    1
    Par défaut
    Bonjour,
    Sur le coût estimé, c'est normal puisque avec variable il estime que le prédicat correspond à 8000 entrées d'index alors qu'en conaissant la valeur (probablement la date qui est récente) c'est beaucoup moins.
    Par contre le coût réel devrait être le même.
    Peux-tu lancer la requête avec autotrace ou tkprof pour voir le nombre de blocs lus ? Le temps peut dépendre de ce qui est en cache.
    Cordialement,
    Franck.

  3. #3
    Rédacteur
    Avatar de Greybird
    Inscrit en
    Juin 2002
    Messages
    673
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 673
    Par défaut
    Bonjour et merci de ta réponse.

    Notre DBA a fini par trouver le souci. Nous appelions ces requêtes depuis du code .NET, et nous bindions un objet de type .NET DateTime dans un paramètre de type DbType.DateTime.

    Or DbType.DateTime correspond au type Oracle TimeStamp. Il fallait utiliser DbType.Date qui correspond au type Oracle Date.

    Cette simple erreur causait le problème de performance indiqué.

    Merci !

    Arnaud

  4. #4
    Expert confirmé 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
    Par défaut
    Franchement je ne crois pas trop à votre solution. Déjà parce qu’un DBA qui fait tourner une base Oracle 10g en mode CHOOSE ce n’est pas un bon signe.

    Je pense plutôt que vous avez être victime d’un phénomène de type introspection des valeurs des variables de liaison, « peek variable binding ». Une investigation plus approfondie pourrait vous éviter des mauvaises surprises dans l’avenir.

  5. #5
    Rédacteur
    Avatar de Greybird
    Inscrit en
    Juin 2002
    Messages
    673
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 673
    Par défaut
    Les paramètres passés avec ces paramètres ont permis de corriger la performance, suite à analyse par un de nos dba.
    Je ne vois pas de raison de douter de son diagnostic en l'état.

    En revanche, merci d'avoir porté ce phénomène de "peek variable binding", je vais étudier le cas et voir si il nous faut creuser plus loin.

    Quand au fait que la base tourne en mode CHOOSE, je leur fait confiance sur la pertinence de ce choix, et d'ailleurs, je ne suis pas qualifié pour le critiquer. S'agissant d'une base critique énorme centralisant des traitements énormes et vieille de plus de 10 ans, avec des critères de disponibilité extrèmes, j'imagine que les changements de versions d'Oracle n'ont pas justifié la prise de risque amenée par un changement de configuration (mais là encore n'étant pas spécialiste, et mon problème de performance étant résolu).

  6. #6
    Expert confirmé 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
    Par défaut
    Bonjour,

    Je vais essayer en quelques mots de vous donner « ma raison ».
    Votre requête paramétrée existe déjà dans le shared pool. Le plan d’exécution qu’elle utilise a été déterminé par la valeur passé dans la variable de liaison (binding variable ou paramètre) au moment du "hard parsing" de la requête. A ce moment un curseur parent et un curseur fils à été crée et stockés dans le shared pool.

    Quand vous avez changé le type de la variable de liaison en utilisant le DbType.Date le curseur parent est resté identique mais le nouveau type de la variable de liaison fait que le curseur fils ne peut plus être utilisé et donc un nouveau plan a été recherché en utilisant cette fois la nouvelle valeur de la variable de liaison. Ce qui à « résolu » en apparence votre problème de performance.

    Jusqu’au là, dans votre cas, ces ne sont que des hypothèses. Mais, pour avancer je pense que vous pouvez faire un test assez simple. L’idée est de ré-exécuter 2 à 3 fois votre requête avec un variable de liaison de type DateTime (celle qui vous posée des soucis) et la valeur de votre exemple mais, en prenant soin de s ‘assurer que le hard parsing a lieu. Pour cella divers méthodes peuvent être employées comme par exemple la modification de la requête par l’ajout d’un alias de la table. Si votre DBA a raison le temps d’exécution de la requête doit reste désastreux : c’est le type de la variable qui pose problème, non ? Si non ou pourrait en discuter.

    Bon courage!

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

Discussions similaires

  1. Sur mobile, les Data URI sont 6 fois plus lentes que les requêtes HTTP
    Par rodolphebrd dans le forum Général Conception Web
    Réponses: 0
    Dernier message: 30/07/2013, 10h32
  2. Réponses: 76
    Dernier message: 29/03/2011, 16h15
  3. [Firebird][Optimisation]Plus lent que le BDE!
    Par vincentj dans le forum Débuter
    Réponses: 3
    Dernier message: 07/02/2005, 15h48
  4. DBExpress est plus lent que BDE?
    Par palassou dans le forum Bases de données
    Réponses: 4
    Dernier message: 02/07/2004, 08h39

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