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 :

performance d'un count avec jointures.


Sujet :

SQL Oracle

  1. #1
    Membre actif
    performance d'un count avec jointures.
    Bonjour,

    Je me casse la tête depuis 1h sur ce problème et je ne parviens pas à trouver ce qui cloche... si vous pouviez m'aider :-)

    Soit là requête ci dessous:
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    SELECT count(fd.file_id)
    	FROM FILE_DECLARATION fd
    	INNER JOIN PARTICIPATION_ACTOR pa on pa.file_id=fd.file_id
    	INNER JOIN ACTOR orderer ON orderer.id= pa.actor_id AND (upper(orderer.DENOM_LNM) LIKE 'A%' )
    	where (upper(fd.CITY_LNM) = 'GENT') AND(fd.POSTCODE = '9000')


    qui prend beaucoup trop de temps.
    De fait, le résultat est 1400 et des poussières.

    Si j'exécute la requête sans le count, on voit que la requête en elle même est très rapide (quelques millisecondes) mais que c'est le 'building output qui prend tout le temps.
    Et j'imagine que quand on fait un count, c'est ce qui se passe côté Oracle (il effectue la requête rapidement, construit l'output et compte les lignes).

    J'ai essayé plein de choses différentes, (count(*), count(1), ...) mais ça ne change rien

    Y'aurait-il un moyen d'accélérer ce count?

    ps: les indexes sont corrects (indexes sur upper, ...) mais, encore une fois, je ne pense pas que le problème soit là.

    Merci :-)

  2. #2
    Modérateur

    Pouvez-vous nous montrer le plan d'exécution de ce count ?

  3. #3
    Membre actif
    voilà :-)



    Rien de bien méchant (j'ai l'impression...)

  4. #4
    Membre habitué
    Bonsoir,

    Un simple select * et select count(*) sur une table change le plan. Le count ne compte donc pas forcément le nombre de lignes du resultset de la même requête sans le count (euh... c'est clair ce que je raconte )
    + sérieusement, tes statistiques sont-elles à jour ?
    Peux-tu fournir le plan de la même requête sans le count ?

  5. #5
    Membre actif
    Je comprends, oui ^^

    Merci pour ta réponse sinon mes stats sont à jour, je les ai recalculées jute avant.


    Voici l'explain plan sans le count:


  6. #6
    Expert éminent sénior
    Est-ce que les cardinalités affichées dans le plan correspondent vraiment à la réalité ? C’est à dire est-ce que seulement 3 enregistrements correspondent aux critères ?
    Il sera bien si t’ajoute la version de la base.

  7. #7
    Membre actif
    bonjour,

    Pour info coun(1), coun(*) ou count (-45646546) font exactement la même chose.
    Seul un count sur une colonne nullable peut apporter des différences puisque le count( ma_col) renverra le nb de lignes avec une valeur dans la colonne en question.

    Sinon par rapport à ta question:
    - Beaucoup trop de temps ca veut dire combien de secondes et tu espères avoir le résultat en combien de secondes
    - quelle volumétrie sur les tables en question.
    Est ce quand dans SQL plus tu peux faire un SET AUTOTRACE ON et envoyer le resultat

    Question subsidiaire : Taille SGA & PGA
    Laurent

  8. #8
    Membre actif
    Heu a priori les cardinalités sont bonnes.

    La version, j'avais oublié de mentionner, on est en Oracle 9.2

    Sinon on vient de me souffler de réorganiser mes indexes pour éviter les table access... je vais faire ça et je vous tiens au courant


    lallio, merci pour les précisions :-)
    Beaucoup de temps = 8 secondes sur des tables ayant +- 1000000 de lignes... c'est pas terrible.

    Pour l'autotrace:



    Pour la taille SGA/PGA aucune idée sorry ;p je ne suis pas le DBA et j'ai comme un affreux doute sur le fait qu'ils acceptent de changer ce param ;p
    (La db est partagée par plusieurs applications)

    Merci

  9. #9
    Membre actif
    Bonjour,

    Désolé, je n'accède pas à l'image...
    sinon pour la sga / Pga à defaut de changer la valeur, ca peut expliquer parfois des pbs
    ex: si sga trop faible, pas de données en cache et donc accès disque (lent)
    si pgs trop faible, choix d'une nested loop au lieux d'un hash (plus performant).
    essai en metten un hint pour forcer une jointure par hash
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    SELECT /*+ USE_HASH (table1,table2)*/ ......




    Laurent

  10. #10
    Membre actif
    Re

    Par rapport à l'autotrace tu vois que tu as 9000 lectures disque + 50000 accès mémoire

    Ca donne quoi au second appel (toujours autant de lectures..)

    Laurent

  11. #11
    Membre actif
    J'ai changé mes indexes entre temps sorry (je vois déjà une nette amélioration)

    sinon pour les accès, pour le count ça ne change rien... sans le count je n'ai plus aucun accès disque la seconde fois...

  12. #12
    Expert éminent sénior
    Citation Envoyé par bidi Voir le message
    Heu a priori les cardinalités sont bonnes.
    ...
    J’ai des forte doutes. Pense tu que pour lire 3 enregistrements dans une table via l’index et 1 seule dans les autres il a besoin des « 9000 lectures disque + 50000 accès mémoire » ?
    Faite une trace SQL ensuite tkprof et vous verrais le nombre des lignes réellement lues.

  13. #13
    Membre actif
    Ca me semble louche aussi ;p

    Sinon pour la trace et tkprof je vais voir comment faire, je ne suis pas dba et je ne sais pas si j'ai les autorisations nécessaires..(haaa les grosses boites ;p)

    Merci pour votre aide

    ps: voici le nouvel explain plan avec les indexes modifiés:



  14. #14
    Membre actif
    pfff c'est n'importe quoi ;p

    voilà la nouvelle trace:




    plus d'accès disque mais 8000000 d'accès mem... c'est grave docteur? ;p
    et c'est toujours lent...

  15. #15
    Membre actif
    Bon, j'arrête de me prendre la tête, en y réfléchissant plus, c'est peut-être bien un comportement normal. Si le range du like est trop grand (genre si je fais un like 'A%') ça prend du temps...Si je suis plus précis ça va tout de suite plus vite (avec les nouveaux indexes).

    Merci pour votre aide, j'ai découvert de nouveaux outils ^^

  16. #16
    Expert éminent sénior
    Sans comprendre ce qui se passe et simplement taper à gauche ou à droit en espérant que c’est le bon coup, cella n’a rien à voir avec l’optimisation. Il me reste de vous souhaiter bon courage et j’espère que vous avez soit une bonne karma soit assez de patience.

  17. #17
    Membre actif
    Je ne suis pas dba et si ça se passe à un niveau tellement bas que je ne peux pas y aller, je ne peux pas faire grand chose de +.

    Là, mes indexes sont bons et ma requête n'est certainement pas la plus mauvaise non plus. Si la DB est mal réglée je ne pourrai de toute façon rien y changer car, comme je l'ai déjà dit, il y a d'autres applications qui tournent dessus et les dbas sont très frileux (genre ils ne voulaient pas recalculer les statistiques sur mes tables de peur de foutre tout par terre).

    Je n'ai pas accès aux outils nécessaires et c'est bien dommage car ça m'intéresse.

    ==> j'arrête de me prendre la tête ^^

    Merci encore pour votre aide

  18. #18
    Expert éminent sénior
    Combien des enregistrements avez-vous dans chaque table ? Quelle sont les indexes sur chaque table, leur description ?
    Comment avez-vous calculé les statistiques ?

    Si vous regardez votre requête en fait vous avez des critères que je pense qu’il sont assez faibles : city_lnm et code_postal sur file_declaration et denom_lnm sur la table actor. Le nom de la ville et le code postal ont très probablement une faible sélectivité. Et le critère sur la table actor, je parle de denom_lnm est au bout de la ligne. Votre première plan montre que l’entrée se fait par la table file_declaration. Beaucoup de ligne se qualifient (tous les enregistrements qui sont dans GENTn, etc). Ensuite toutes les participation sont scanées. Et pour chaque entrée du file_id il y a probablement N références à l’acteur. Et seulement ensuite on attaque la table actor très probablement pour éliminer la plus part des enregistrements ramenées parce que elle ne passent pas le filtre sur denom_lnm.

    Mais vous avez certainement un problème de calcul des statistiques. Le plan que vous montrez c’est bien celui qui corresponde à la requête : pas de variable binding, ni rien d’autre ?

  19. #19
    Membre actif
    Très instructif merci :-)

    Pour les stats, je pense que je vais me faire allumer mais je fais ça avec un analyze table X compute statistics... en Test.

    Je ne sais pas comment font les dbas en production, j'imagine la même chose. Mais j'ai lu quelque part que ce n'est pas la meilleure façon de faire.

    Comment puis-je faire autrement?

  20. #20
    Expert éminent sénior
    en sqlplus
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
     
    exec dbms_stats.gather_table_stats(user, 'EMP', cascade=>true)

    il faut le faire pour chaque table bien sûr.