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 :

Temps d'exécution etonnant


Sujet :

SQL Oracle

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Bj0
    Bj0 est déconnecté
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2006
    Messages : 8
    Par défaut Temps d'exécution etonnant
    salut,
    je ne comprend pas trés bien mes temps d'exécution de ma Requete SQL que j 'exécute sur une base de données oracle.
    Ma requete est bien évidenment longue a s'exécuter ( 1 UNION et une jointure de 4 tables dans chaque partie et ces tables peuvent atteindre plus de 20 M de lignes (M= Million bien sur :p))
    la voici (attention aux yeux ) :

    (SELECT
    substr((D.VAL_NUMERIQUE_15/3600000),1,3) as FV,
    A.MATRICULE_EMPLOYE as matricule,
    substr(D.ID_EMPLOYE,1,5)as ID,
    to_char (B.DTJ_DEB,'YYYYMMDD'),
    to_char (B.DTJ_FIN,'YYYYMMDD'),
    substr(C.VALEUR_CARACTERE,1,1),
    (to_char (D.DTJ_VALORISATION,'YYYYMMDD'))
    FROM
    EMP_EMPLOYES A,
    EMP_PERIODES B,
    DIC_VALEURS_CHP_HISTOS_SYNTHES C,
    CPT_VALEURS_YYYYXX1 D
    WHERE
    ( A.ID_EMPLOYE = B.ID_EMPLOYE
    AND A.ID_EMPLOYE = C.ID_ENTITE_FONCTIONNELLE(+)
    AND A.ID_EMPLOYE = D.ID_EMPLOYE
    AND
    B.DTJ_FIN between C.DTJ_DEB and C.DTJ_FIN
    AND B.DTJ_FIN = D.DTJ_VALORISATION
    AND to_char (B.DTJ_FIN ,'YYYYMMDD') BETWEEN
    #DATE_DEBUT#
    AND #DATE_FIN#
    AND
    A.MATRICULE_EMPLOYE BETWEEN '01' AND '51'
    AND
    C.ID_CHAMP_PERSO = 'H30'
    AND A.ID_EMPLOYE in
    (
    SELECT
    ID_ENTITE_FONCTIONNELLE
    FROM
    DIC_VALEURS_CHP_HISTOS_SYNTHES
    WHERE
    ID_CHAMP_PERSO = 'J10'
    AND VALEUR_CARACTERE = '0'
    )
    )
    )
    UNION
    (SELECT
    substr((D.VAL_NUMERIQUE_15/3600000),1,3) as FV,
    A.MATRICULE_EMPLOYE as matricule,
    substr(D.ID_EMPLOYE,1,5)as ID,
    to_char (B.DTJ_DEB,'YYYYMMDD'),
    to_char (B.DTJ_FIN,'YYYYMMDD'),
    substr(C.VALEUR_CARACTERE,1,1),
    (to_char (D.DTJ_VALORISATION,'YYYYMMDD'))
    FROM
    EMP_EMPLOYES A,
    EMP_PERIODES B,
    DIC_VALEURS_CHP_HISTOS_SYNTHES C,
    CPT_VALEURS_YYYYXX1 D
    WHERE
    ( A.ID_EMPLOYE = B.ID_EMPLOYE
    AND A.ID_EMPLOYE = C.ID_ENTITE_FONCTIONNELLE(+)
    AND A.ID_EMPLOYE = D.ID_EMPLOYE
    AND
    D.DTJ_VALORISATION in (#DATE_FIN_ANNEE_1#,
    #DATE_FIN_ANNEE_2#)
    AND D.DTJ_VALORISATION between B.DTJ_DEB and B.DTJ_FIN
    AND D.DTJ_VALORISATION between C.DTJ_DEB and C.DTJ_FIN
    AND
    A.MATRICULE_EMPLOYE BETWEEN '01' AND '51'
    AND
    C.ID_CHAMP_PERSO = 'H30'
    AND A.ID_EMPLOYE in
    (
    SELECT
    ID_ENTITE_FONCTIONNELLE
    FROM
    DIC_VALEURS_CHP_HISTOS_SYNTHES
    WHERE
    ID_CHAMP_PERSO = 'J10'
    AND VALEUR_CARACTERE = '0'
    )
    )
    )
    ORDER BY matricule;



    lorsque je remplace :
    #DATE_DEBUT# par '1-1-2006'
    #DATE_FIN# par '31-12-2008'
    #DATE_FIN_ANNEE_1# par '31-12-2006'
    #DATE_FIN_ANNEE_2# par '31-12-2007'

    Cette requète met environ 2 min ... ( je trouve le temps pas mal et il me convient)
    mais ces valeur ne doivent pas êtres écrite ainsi " en dur" elle doivent etre recherché dans une table de 1 seule ligne

    mais quand je remplace :
    #DATE_DEBUT# par (SELECT Date_debut FROM periodeTmp)
    #DATE_FIN# par (SELECT Date_fin FROM periodeTmp)
    #DATE_FIN_ANNEE_1# par (SELECT Date_fin_annee_1 FROM periodeTmp)
    #DATE_FIN_ANNEE_2# par (SELECT Date_fin_annee_2 FROM periodeTmp)

    Ces sous requètes ne sont pa liées,la vitesse d exécution de cette nouvelle requete devrait être quasiment la même que la précédente
    or ce n'est pa du tout le cas : il met environ 2 h a sexécuter mais donne bien le bon résultat.

    je ne pense pas que ce soit une erreur de format. ( ils sont tous format DATE)

    a quoi est dut cette différence ?


    Merci d'avance

  2. #2
    Rédacteur

    Homme Profil pro
    Développeur et DBA Oracle
    Inscrit en
    Octobre 2006
    Messages
    878
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur et DBA Oracle

    Informations forums :
    Inscription : Octobre 2006
    Messages : 878
    Par défaut
    Salut,

    Ma premiére remarque pourquoi tu utilises le select in, remplaces le avec une jointure.( il fait un full table scan)
    exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    AND A.ID_EMPLOYE in 
    (
    SELECT
    ID_ENTITE_FONCTIONNELLE
    FROM
    DIC_VALEURS_CHP_HISTOS_SYNTHES
    WHERE
    ID_CHAMP_PERSO = 'J10'
    AND VALEUR_CARACTERE = '0'
    )
    Ce select te retournes combien d'enregistrements
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    (SELECT Date_debut FROM periodeTmp)
    J'aimerai bien voir ton script de remplacement, si c'est possible

  3. #3
    Membre Expert
    Inscrit en
    Avril 2006
    Messages
    1 024
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 1 024
    Par défaut
    L'écriture différente de la requête doit amener oracle à choisir un plan d'exectution différent ce qui change les temps d'exécution.

    Quelques chtites remarques et questions à se poser:
    - as tu passé les stats sur ton schéma ?

    Sinon commence par faire ça avant de continuer.

    - Combien de lignes est sensée de ramener ce type de requête (ordre de grandeur)
    - Si peu de ligne sont ramenées, alors il faut savoir quel est le(s) critère(s) le(s) plus discriminant(s). En fonction de ça, tu sera peut etre amené à créer des index ciblés.
    - Attention la clause " to_char (B.DTJ_FIN ,'YYYYMMDD') BETWEEN DATE_DEBUT# AND #DATE_FIN# " ne peut pas utiliser un éventuel index sur B.DTJ_FIN car c'est un calcul.

  4. #4
    Bj0
    Bj0 est déconnecté
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2006
    Messages : 8
    Par défaut
    Ce select te retournes combien d'enregistrements

    Code :
    (SELECT Date_debut FROM periodeTmp)

    ->1 seul


    as tu passé les stats sur ton schéma ?
    ->non et je ne sais pas le faire

    Combien de lignes est sensée de ramener ce type de requête (ordre de grandeur)
    -> 25 000


    Si peu de ligne sont ramenées, alors il faut savoir quel est le(s) critère(s) le(s) plus discriminant(s). En fonction de ça, tu sera peut etre amené à créer des index ciblés.
    -> impossible de créé des index c'est une base de données fournie avec un progiciel et il ne vaut mieu pas la changer ca risque de foutre pas mal de bordel ( mmmmh a tester... :p)

    J'aimerai bien voir ton script de remplacement,
    -> qu'entend tu par script de remplacement? mon programme perl ki change les paramètre en #xxxx# par la valeur voulu?
    meme sans ce remplacement j'ai le meme probleme donc ca ne vien pas de la...

  5. #5
    Bj0
    Bj0 est déconnecté
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2006
    Messages : 8
    Par défaut
    en réalité c'est plus cette partie la qui pose probleme ...

    D.DTJ_VALORISATION in (#DATE_FIN_ANNEE_1#,
    #DATE_FIN_ANNEE_2#)

    car celle si

    to_char (B.DTJ_FIN ,'YYYYMMDD') BETWEEN
    #DATE_DEBUT#
    AND #DATE_FIN#

    met autant de temps avec une sous requète que les valeur écrite "en dur"

  6. #6
    Membre Expert
    Inscrit en
    Avril 2006
    Messages
    1 024
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 1 024
    Par défaut
    Commence par passer les stats sur ton schéma:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    BEGIN
    dbms_stats.gather_schema_stats( 'ton_schema');
    END;

Discussions similaires

  1. Réponses: 9
    Dernier message: 20/06/2005, 12h17
  2. [C#] Calcul du temps d'exécution.
    Par lozzko dans le forum Windows Forms
    Réponses: 4
    Dernier message: 12/06/2005, 16h12
  3. Réponses: 2
    Dernier message: 25/05/2004, 15h33
  4. Affichage du temps d'exécution d'une requête
    Par milka dans le forum PostgreSQL
    Réponses: 1
    Dernier message: 22/03/2004, 17h48
  5. Temps d'exécution des instructions FPU
    Par ubi dans le forum Assembleur
    Réponses: 2
    Dernier message: 24/10/2003, 18h39

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