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

 Oracle Discussion :

Utilisation des index dans une requête


Sujet :

Oracle

  1. #21
    Nouveau membre du Club
    Homme Profil pro
    Inscrit en
    Juin 2010
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juin 2010
    Messages : 56
    Points : 26
    Points
    26
    Par défaut
    Essayez avec un index non pas sur num_serie mais sur to_number(serie).
    en créant un index sur to_number(num_serie),la requête quitte de 20s 33 à 1min 16.elle devient plus lente!!

  2. #22
    Membre actif Avatar de DAB.cz
    Inscrit en
    Octobre 2006
    Messages
    221
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 221
    Points : 249
    Points
    249
    Par défaut
    Citation Envoyé par sanouphil Voir le message
    en créant un index sur to_number(num_serie),la requête quitte de 20s 33 à 1min 16.elle devient plus lente!!
    Miracle

    Mais encore une fois:
    Citation Envoyé par Waldar Voir le message
    ... si vous stockez des nombres vous devez utiliser le format NUMBER et pas VARCHAR2.

  3. #23
    Nouveau membre du Club
    Homme Profil pro
    Inscrit en
    Juin 2010
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juin 2010
    Messages : 56
    Points : 26
    Points
    26
    Par défaut
    ... si vous stockez des nombres vous devez utiliser le format NUMBER et pas VARCHAR2.
    ok je vais devoir détruire mes données avant de modifier mon schéma.
    ok j'ai pas le choix apparemment. à plus!je vais essayé ca.a plus

  4. #24
    Membre actif Avatar de DAB.cz
    Inscrit en
    Octobre 2006
    Messages
    221
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 221
    Points : 249
    Points
    249
    Par défaut
    ex. 1a
    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
    create table num_serie_montant (
      montant number,
      num_serie varchar2 (9));
    create index num_serie_montant_ii on
      num_serie_montant (num_serie);
    
    insert into num_serie_montant (montant, num_serie)
      select trunc (level / 1000), to_char (level) from dual connect by level <= 10000000;
    commit;
    
    set timing on
    
    declare
      xstart number := 450;
      xend number := 5000;
      xres number;
    begin
      SELECT count(DISTINCT montant) 
        into xres
        FROM num_serie_montant 
        WHERE to_number(num_serie)  BETWEEN xstart  AND xend;
    end;
    /
    
    00:00:13.49
    -- pas bon
    ex. 1b:
    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
    create index x on
      num_serie_montant (to_number(num_serie));
    
    declare
      xstart number := 450;
      xend number := 5000;
      xres number;
    begin
      SELECT count(DISTINCT montant) 
        into xres
        FROM num_serie_montant 
        WHERE to_number(num_serie)  BETWEEN xstart  AND xend;
    end;
    /
    
    -- avec index "to_number" - ok
    00:00:00.43
    ex. 2
    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
    create table num_serie_montant (
      montant number,
      num_serie varchar2 (9));
    create index num_serie_montant_ii on
      num_serie_montant (num_serie);
    
    insert into num_serie_montant (montant, num_serie)
      select trunc (level / 1000), lpad (to_char (level), 9, '0') from dual connect by level <= 10000000;
    commit;
    
    declare
      xstart varchar2 (9) := '000000450';
      xend varchar2 (9) := '000005000';
      xres number;
    begin
      SELECT count(DISTINCT montant) 
        into xres
        FROM num_serie_montant 
        WHERE num_serie  BETWEEN xstart  AND xend;
    end;
    /
    
    -- ok
    00:00:00.90
    ex. 3 (la meilleure solution)
    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
    create table num_serie_montant (
      montant number,
      num_serie number (9));
    create index num_serie_montant_ii on
      num_serie_montant (num_serie);
    
    insert into num_serie_montant (montant, num_serie)
      select trunc (level / 1000), level from dual connect by level <= 10000000;
    commit;
    
    declare
      xstart number := 450;
      xend number := 5000;
      xres number;
    begin
      SELECT count(DISTINCT montant) 
        into xres
        FROM num_serie_montant 
        WHERE num_serie  BETWEEN xstart  AND xend;
    end;
    /
    
    -- ok
    00:00:00.73

  5. #25
    Nouveau membre du Club
    Homme Profil pro
    Inscrit en
    Juin 2010
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juin 2010
    Messages : 56
    Points : 26
    Points
    26
    Par défaut
    merci beaucoup à toi pour vos propositions de solutions .c'est vraiment cool!mais dites moi DAB.cz pour la meilleure solution,cette partie sert à quoi?moi je charge mes numéros de serie et montant via sql loader
    insert into num_serie_montant (montant, num_serie)
    select trunc (level / 1000), level from dual connect by level <= 10000000;
    commit;
    .
    juste pour comprendre un peu plus ca
    select trunc (level / 1000), level from dual connect by level <= 10000000;
    commit;
    .c'est vraiment très cool à toi.je vais les tester.

  6. #26
    Membre actif Avatar de DAB.cz
    Inscrit en
    Octobre 2006
    Messages
    221
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 221
    Points : 249
    Points
    249
    Par défaut
    J'ai voulu insérer quelques lignes (1000000).

    Explanation:
    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
    SQL> select trunc (level / 10), level
      2    from dual
      3    connect by level <= 25;
     
    TRUNC(LEVEL/10)     LEVEL
    --------------- ---------
                  0         1
                  0         2
                  0         3
                  0         4
                  0         5
                  0         6
                  0         7
                  0         8
                  0         9
                  1        10
                  1        11
                  1        12
                  1        13
                  1        14
                  1        15
                  1        16
                  1        17
                  1        18
                  1        19
                  2        20
                  2        21
                  2        22
                  2        23
                  2        24
                  2        25
    C'est la requête hiérarchique sur la table interne "dual"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SQL> select * from dual;
     
    D
    -
    X

  7. #27
    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
    Ne comptez plus les montants distincts. Affectez directement le libelle du montant à la zone libellé. Quand il aurait plusieurs montants correspondant à la plage il y aura une erreur dans le select d’affectation que vous pouvez intercepter et afficher un message explicite.
    Bref, y compris avec votre algorithme ça doit bien se passer. Donc vous devez fournir un peu plus du code et des explications pour qu’on arrive à identifier ce qui ne va pas.

  8. #28
    Nouveau membre du Club
    Homme Profil pro
    Inscrit en
    Juin 2010
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juin 2010
    Messages : 56
    Points : 26
    Points
    26
    Par défaut
    J'ai voulu insérer quelques lignes (1000000).
    ah ok j'ai compris.moi je charge avec Sql loader.ca ne doit pas poser de problème donc.merci

  9. #29
    Membre éprouvé
    Inscrit en
    Avril 2006
    Messages
    1 024
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 1 024
    Points : 1 294
    Points
    1 294
    Par défaut
    J'ai un peu l'impression qu'on parle un peu dans le flou là puisqu'il manque des infos...

    Sanouphil, tu nous a montré le curseur, mais qu'est-ce qui te dis que c'est ce curseur qui pose problème (bien que je soit d'accord avec les remarques précédentes)

    Je suppose que ton curseur sert à piloter une boucle, qu'y-a-t-il comme traitement à chaque itération de la boucle ?

  10. #30
    Nouveau membre du Club
    Homme Profil pro
    Inscrit en
    Juin 2010
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juin 2010
    Messages : 56
    Points : 26
    Points
    26
    Par défaut
    Ne comptez plus les montants distincts. Affectez directement le libelle du montant à la zone libellé. Quand il aurait plusieurs montants correspondant à la plage il y aura une erreur dans le select d’affectation que vous pouvez intercepter et afficher un message explicite.
    Bref, y compris avec votre algorithme ça doit bien se passer. Donc vous devez fournir un peu plus du code et des explications pour qu’on arrive à identifier ce qui ne va pas.
    .
    Mon premier curseur est comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    cursor cnt is
    	      select count(distinct montant) 
    	           from activation.num_serie_montant 
    	            where num_serie  between :starting_id
    	          and  :ending_id;
    mon deuxième curseur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     cursor mnt is
    	      select distinct montant
    	             from activation.num_serie_montant
    	             where num_serie  between :starting_id
    	             and :ending_id;
    Ensuite j'ouvre mes curseurs comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    open cnt; fetch cnt into nbr; close cnt;
       	if nbr > 1 then
              message alert
           elsif nbr=0
           message alert
    else
    J'ouvre mon second curseur comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    open mnt; fetch mnt into v_montant; close mnt;
    Et j'affecte les valeurs récupérées aux différents champs.
    il y a un autre curseur qui contient la jointure entre la table produit et la table num_serie_montant.
    J'espère que c'est plus clair maintenant.

    Merci.

  11. #31
    Membre éprouvé
    Inscrit en
    Avril 2006
    Messages
    1 024
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 1 024
    Points : 1 294
    Points
    1 294
    Par défaut
    Petite remarque, ton premier curseur est inutile étant donné que tu ne ramènes qu'une seule valeur, fait plutot:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT count(DISTINCT montant) into nbr
      FROM activation.num_serie_montant 
        WHERE num_serie  BETWEEN starting_id
        AND  ending_id;
    ça revient au même mais c'est plus vite écrit!


    Etant donné tu sors lorsqu'il y a plusieurs montants, ça veut dire que ton 2ieme curseur lui aussi ne renvoit qu'une valeur!

    Tu peux donc faire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    SELECT DISTINCT montant into v_montant 
      FROM activation.num_serie_montant
      WHERE num_serie  BETWEEN :starting_id
       AND :ending_id;
    étant donné que tu fais 2 fois le meme parcours pour une fois vérifier, et une autre fois charger ta variable, tu peux mutualiser par exemple par


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT 
      MAX(montant) , count (distinct v_montant) into v_montant, nbr 
     FROM activation.num_serie_montant
      WHERE num_serie  BETWEEN starting_id
       AND ending_id;
    ça marchera exactement pareil et tu économiseras un parcours de table et là de 2 choses l'une:
    - soit tu a divisé tes temps par 2 (enfin un peu moins à cause du cache) et tu as un pb de très gros volume de données dans ta table
    - soit ça n'a rien changé (ce que je crois) et ça veut dire que le pb vient de l'autre partie que tu n'as pas montré

  12. #32
    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
    Il faut aussi la syntaxe du dernier curseur, afin qu'on puisse tous les supprimer !

  13. #33
    Nouveau membre du Club
    Homme Profil pro
    Inscrit en
    Juin 2010
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juin 2010
    Messages : 56
    Points : 26
    Points
    26
    Par défaut
    Petite remarque, ton premier curseur est inutile étant donné que tu ne ramènes qu'une seule valeur, fait plutot:
    ainsi cela veut-il dire que je n'aurai plus besoin de mes curseurs?

  14. #34
    Membre éprouvé
    Inscrit en
    Avril 2006
    Messages
    1 024
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 1 024
    Points : 1 294
    Points
    1 294
    Par défaut
    Citation Envoyé par sanouphil Voir le message
    ainsi cela veut-il dire que je n'aurai plus besoin de mes curseurs?
    Oui, pour oracle, il se passe un peu la même chose, mais c'est complètement transparant pour toi, et quand meme bien plus vite écrit et plus clair.

    Ceci dit, j'ai l'impression que le pb ne vient pas de là... mais à tester...

  15. #35
    Nouveau membre du Club
    Homme Profil pro
    Inscrit en
    Juin 2010
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juin 2010
    Messages : 56
    Points : 26
    Points
    26
    Par défaut
    la syntaxe du dernier curseur est ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     CURSOR C IS
        SELECT libellé,prix_unitaire
      	FROM produits
        WHERE code_produit=code_plage;
    ensuite j'ouvre mon curseur et j'affecte le libellé à la forms
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     begin
        open c; fetch c into :libellé,:prix_unitaire;close c;
    	:forms.libellé:=:libellé;
    et c'est tout!
    j'espère encore que c'est claire!
    merci pour votre aide

  16. #36
    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
    Comment faites-vous le lien entre code_plage et le curseur précédent, est-ce le montant du deuxième curseur ?

  17. #37
    Membre éprouvé
    Inscrit en
    Avril 2006
    Messages
    1 024
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 1 024
    Points : 1 294
    Points
    1 294
    Par défaut
    là aussi si tu es sur que ton curseur ne te ramène qu'une ligne, tu peux faire un "select into"

    A priori si c'est cette dernière requete qui est la cause, ça peut venir de 2 trucs:
    - Est-ce que ta table produits est bien indexée sur "code_produit" ?
    - Est-ce que la variable code_plage est du même type que "code_produit" car si jamais la variable est de type number et que la colonne est de type varchar2, il peut y avoir une réécriture implicite de la requête par

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    to_number(code_produit) = code_plage
    Et du coup ça ne passe plus par l'index de code_produit. Il faut donc soit faire un index sur le to_number là aussi, soit se débrouiller pour que les types soient les mêmes.

  18. #38
    Nouveau membre du Club
    Homme Profil pro
    Inscrit en
    Juin 2010
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juin 2010
    Messages : 56
    Points : 26
    Points
    26
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Comment faites-vous le lien entre code_plage et le curseur précédent, est-ce le montant du deuxième curseur ?
    le lien entre les curseurs est que la table produits dispose déjà à l'avance des montants et des libellés que peut prendre une plage donnée.donc effectivement c'est le montant du deuxième curseur qui fait le lien

  19. #39
    Nouveau membre du Club
    Homme Profil pro
    Inscrit en
    Juin 2010
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juin 2010
    Messages : 56
    Points : 26
    Points
    26
    Par défaut
    Et du coup ça ne passe plus par l'index de code_produit. Il faut donc soit faire un index sur le to_number là aussi, soit se débrouiller pour que les types soient les mêmes.
    j'ai pas d'index sur le code du produit enfin je n'en ai pas crée.faut-il que je le fasse?et puis la colonne code_produit est effectivement de type varchar2(7) et libellé de type VARCHAR2(30).je vais donc changer le type du code produit pour voir.
    Merci pour la remarque.

  20. #40
    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
    Si j'ai bien tout compris (et j'ai un sérieux doute car vous livrez les informations au compte-goute, c'est un peu pénible), vous pouvez tout synthétiser en une seule requête :
    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
    SELECT case count(distinct prd.code_produit)
             when 1 then 'OK'
             else 'Plusieurs produits sur la plage saisie'
           end as statut,
           case count(distinct prd.code_produit)
             when 1 then min(prd.libellé)
           end as libellé,
           case count(distinct prd.code_produit)
             when 1 then min(prd.prix_unitaire)
           end as prix_unitaire
      INTO :statut, :libellé, :prix_unitaire
      FROM activation.num_serie_montant nsm
           inner join produits prd
             on prd.code_produit = nsm.montant
     WHERE to_number(nsm.num_serie) BETWEEN :starting_id AND :ending_id;

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 4 PremièrePremière 1234 DernièreDernière

Discussions similaires

  1. [MySQL] Utilisation des alias dans une requête
    Par methodman225 dans le forum PHP & Base de données
    Réponses: 4
    Dernier message: 29/09/2008, 12h55
  2. Utilisation des parametres dans une requéte
    Par ange_dragon dans le forum Requêtes et SQL.
    Réponses: 2
    Dernier message: 13/06/2007, 09h32
  3. Utiliser des "SI" dans une requête access ?
    Par shaenwe dans le forum Requêtes et SQL.
    Réponses: 3
    Dernier message: 14/03/2007, 12h25
  4. Comment utiliser des variables dans une requête SQL ?
    Par Ragnarok85 dans le forum Requêtes et SQL.
    Réponses: 10
    Dernier message: 12/02/2007, 16h23

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