|
Publicité ' | ||||||||||||||||||||||||
|
|
#1 | |||
|
Membre Expert
![]() Sylvain DevidalChef de projets Générix Inscription : février 2010 Messages : 1 062 ![]() |
Bonjour,
Je travaille avec une base de données Oracle 10g : Citation:
Contrats : CNT (CODSOC, ACHVTE, NUMCNT, ...) Postes de contrats CNP (CODSOC, ACHVTE, NUMCNT, TQOI, CODPRO, DATAPP, ...) En souligné : INDEX UNIQUE faisant office de clé primaire. Il n'y a pas de notion de clé primaire ni de clé étrangère définie dans la base (oui, je sais, c'est pourri mais c'est comme ça). Le tuple CNP (CODSOC, ACHVTE, NUMCNT) permet de rattacher des postes à un contrat. Je dois rechercher tous les contrats (sans doublon) pour lesquels il existe au moins un poste avec DATAPP vide (égale à ' '). J'ai écrit trois requêtes (existe-t-il d'autres méthodes) ? Code :
- Les deux premières ont strictement le même plan d'exécution. - Les trois ont un plan d'exécution qui a le même coût (554). La troisième requête, pourtant plus naturelle pour le SGBD, est 2 fois plus lente (~0,2 seconde contre ~0,1 seconde pour les deux premières). La première semble plus rapide que la seconde, alors qu'elle a le même plan d'exécution (en exécutant une dizaine de fois chacune des deux requêtes, la première est presque toujours < 0,1 alors que la seconde est presque toujours > 0,1). Ce poste est motivé par la volonté de comprendre pourquoi telle syntaxe est plus rapide qu'une autre (alors qu'on fait exactement la même chose) et comment tirer une règle générale lors de l'écriture des requêtes. Ce qui m'étonne, c'est que j'ai souvenir d'avoir préféré longtemps le EXIST plutôt que le DISTINCT/INNER JOIN et le IN, alors que le IN était plus rapide à une certaine époque (la 8i il me semble, ou la 9g), et que le DISTINCT/INNER JOIN est plus rapide avec SQL Server par exemple. A part benchmarker chaque requête que j'écris, existe-t-il une règle générale ? |
|||
|
|
00
|
|
|
#2 |
|
Expert Confirmé Sénior
![]() ![]() Marius NituIngénieur développement logiciels Inscription : octobre 2007 Messages : 3 311 ![]() |
L’optimiseur de requête prend la liberté de transformer vos requêtes comme bon lui semble ! Dans votre exemple les deux premières requêtes sont transformées de la même façon.
La troisième requête donne le même résultat mais ne fait pas le même travail, vous avez en fait remplacée une semi-jointure par une jointure. |
|
|
10
|
|
|
#3 | |
|
Membre Expert
![]() Inscription : août 2008 Messages : 1 271 ![]() |
Citation:
Le seul intérêt du coût est de comprendre pourquoi oracle a chosit un index ou un FTS, un hash join ou un nested loop pour une même requête. Le coût le plus faible étant probablement la méthode d'accès choisie. Mais là encore ce n'est pas forcément la méthode d'accès la plus performante. Si le CBO en amont n'a pas les bonnes infos (statistiques) ou a des infos incomplètes, le coût déterminé sera faux. Concernant le coût tu peux lire Comment l'optimiseur d'Oracle calcule le coût,et également faire un tour sur la bibliographie. Concernant tes intérogations sur les précédentes versions tu peux lire IN & EXISTS (poste qui remonte à l'année 2000), mais comme tu l'as constaté les choses changent le CBO évolue, un peu plus bas dans la discussion on peu lire IN and Inner Join Pour en revenir à la performance des 3 approches, pour les comparer il faut regarder la ligne CONSISTENT GET de l'autotrace. |
|
|
|
00
|
|
|
#4 |
|
Membre chevronné
![]() O. JolySupport Inscription : décembre 2010 Messages : 287 ![]() |
Pour autant que je sache, et autant que cela est possible il est préférable de remplacer les sous requêtes (requêtes dans la clause where) par des vues dynamiques (requêtes dans la clause "from" qui peuvent aussi être écrites avant le select dans une clause "with").
Maintenant, comme le dit mnitu Oracle en interne lors du parsing oracle tente une réécriture des requêtes et choisis généralement le type de requête sans sous requêtes et avec de vues dynamiques, bref celle qui, selon vos termes, lui "semble la plus naturelle". Coté tuning, et c'est toujours un avis personnel, il n'est pas forcément nécessaire de tuner chaque requête, les plus consommatrices en temps sont celles qui méritent de l'être (tunées). |
|
00
|
|
|
#5 |
|
Membre expérimenté
![]() Mohamed HouriInscription : mars 2010 Messages : 286 ![]() |
En règle générale, puisque vous parlez de règle générale si tant est qu’une règle générale existe en ORACLE, à chaque fois que vous devez analyser la performance d’une requête SQL ou simplement lorsque vous voulez comprendre le choix fait par Oracle (CBO) pour exécuter votre requête vous devez passer par un explain plan. Dans ce cas vous devez:
Code :
SELECT * FROM TABLE(dbms_xplan.display_cursor(NULL,NULL, ‘ALLSTATS LAST’)) ; Pour revenir à votre cas, je vous conseille:
http://jonathanlewis.wordpress.com/2011/06/23/video/ dont j’ai l’intention d’en faire un résumé en français un de ces jours. |
|
|
11
|
|
|
#6 | |
![]() Inscription : décembre 2002 Messages : 2 387 ![]() |
Citation:
Oups, désolé, je n'avais pas vu l'intervention de Mohamed.
__________________
Consultant / formateur Oracle indépendant Certifié OCP 10g et 11g, sécurité 11g |
|
|
|
00
|
|
|
#7 | |
![]() Inscription : décembre 2002 Messages : 2 387 ![]() |
Citation:
Mais de manière générale, l'algorithme de coût prenant en compte non seulement les lectures logiques, mais aussi la charge CPU induite, il n'y a pas de raison de se focaliser uniquement sur les CONSISTENT GET.
__________________
Consultant / formateur Oracle indépendant Certifié OCP 10g et 11g, sécurité 11g |
|
|
|
00
|
|
|
#8 | |
|
Expert Confirmé Sénior
![]() ![]() Marius NituIngénieur développement logiciels Inscription : octobre 2007 Messages : 3 311 ![]() |
Citation:
@Mohamed Houri Sour ce point je trouve que vous avez une approche DBA rigide: requête => problème => analyse => solution=>test=>validation=>résolue. Or la question ici est la suivante : comment écrire la requête d’une manière proactive, avant que le problème arrive ! Et peu importe l’explain plan. |
|
|
|
00
|
|
|
#9 | ||
|
Membre Expert
![]() Inscription : août 2008 Messages : 1 271 ![]() |
Citation:
Consider Cost or Time - trying to compare the COST of two queries C'est sûr cette discussion a débuté il y a longtemps sur de vieux produits les choses se sont sûrement améliorées. Si 3 requêtes donnent le même résultat avec des plans différents, je regarde les Logical IO, le moins il y en a, le moins il y aura de physical IO. C'est déjà un bon moyen de sélectionner quelle requête est la plus pertinante, non ? Mais je suis d'accord que le CPU peut être un autre facteur important (un peu plus bas dans la page): Citation:
|
||
|
|
00
|
|
|
#10 |
|
Membre expérimenté
![]() Mohamed HouriInscription : mars 2010 Messages : 286 ![]() |
Marius,
Vous pouvez écrire la requête comme bon vous semble, si la performance vous est acceptable vous vous arrêterez là. Si par contre la performance n’est pas acceptable et que vous embarquez immédiatement dans la réécriture de la requête c’est que vous avez conclu sans preuve ni évidence que la lenteur de la requête provient de son écriture et qu’il suffit d’une réécriture adéquate et le tour est joué !!! C’est ce que j’appelle ‘’Hit and Try’’ ou changeant et voyant ce qui se passe. Il se peut que cela fonctionne parfaitement ; mais il se peut que malgré vos efforts de réécriture le CBO continue de choisir un chemin non performant à cause de l’absence d’information reflétant la réalité de la distribution des données ou à cause de de l’absence d’index précis pour couvrir la requête. C’est clair qu’ici je ne parle pas des requêtes où des clauses WHERE et AND sont inutiles ou une jointure est manquante ou une jointure est en trop, ou etc… Je parle d’une requête cohérente comme celle présentée dans l’exemple qui a conduit à cette discussion. L’école que je suis m’a enseigné de regarder l’explain plan aux fins d’y trouver l’explication à toute lenteur. Parfois, et même souvent, une réécriture de la requête permet d’aboutir à un temps de réponse acceptable. N’empêche que cette réécriture m’est dictée par l’explain plan. Lorsque je constate, par exemple, que je commence par une opération qui génère 145.000 lignes pour ne laisser à la fin qu’une centaine de lignes, alors dans ce cas, j’utilise le très formidable axiome de Jonathan Lewis: ‘’Eliminate Earlier, start small and try to keep small ‘’, qui veut dire dans la langue de Molliere :’’Eliminez des lignes le plutôt possible, commencer avec un petit volume et essayer de maintenir ce petit volume’’, afin de réécrire ma requête. Tout cela je le vois bien dans mon explain plan alors que je ne le vois pas dans ma requête surtout si je suis amené à améliorer la performance d’une application dont je ne connais pas la nature et la répartition des données. je répète que je parle de requêtes cohérentes. |
|
|
00
|
|
|
#11 | ||||
![]() Inscription : décembre 2002 Messages : 2 387 ![]() |
Citation:
Intellectuellement, la méthode par essais / corrections me désole, mais force est de constater que personne n'a encore trouvé le Graal (ou alors tu t'es bien gardé de nous en faire part). A part quelques réglounettes basiques, personne à ma connaissance ne propose rien de concret. Ca me fait bien marrer de lire, régulièrement, que le SQL est un langage non procédural dans lequel il suffit de spécifier ce qu'on recherche, et non pas comment le trouver. Dès lors qu'on se préoccupe des performances, cette affirmation est une escroquerie, car il devient indispensable de comprendre la logique interne de l'optimiseur, c'est à dire son algorithme ! Face aux problèmes de performances, on peut distinguer plusieurs écoles, en particulier les suivantes : 1) la méthode que je dirais fonctionnaliste, qui reste au niveau SQL Selon Stéphane Faroult dans "refactoring SQL applications" Citation:
Citation:
Dan Tow avec son "SQL Tuning" en est sans doute le représentant ultime, lui qui prétend qu'on peut en quelque sorte faire de l'optimisation symbolique, sans même comprendre les requêtes. 3) Celle qui ne jure que par l'analyse de la trace étendue (10046) 4) Une petite nouvelle, cheval de bataille de Grégory Guillou : Citation:
Quant à la quatrième, j'ignore ce qui se cache concrètement derrière...
__________________
Consultant / formateur Oracle indépendant Certifié OCP 10g et 11g, sécurité 11g |
||||
|
|
11
|
|
|
#12 | ||
|
Expert Confirmé Sénior
![]() ![]() Marius NituIngénieur développement logiciels Inscription : octobre 2007 Messages : 3 311 ![]() |
Mohamed,
La question est bien : comment je dois écrire cette requête pour qu’elle ne pose pas des problèmes des performances à l’exploitation de l’application. Encore plus précis : je peux obtenir le même résultat correct en écrivant N requêtes différentes et syntactiquement correctes. Est-ce que la performance est la même pour tout l’espace des requêtes possible ou pas ? Il n’y a pas de plan d’exécution ! Il n’y pas de problème ! Il n'y pas de lenteur! Qu’est-ce que vous nous conseiller : Citation:
Citation:
|
||
|
|
00
|
|
|
#13 |
|
Expert Confirmé Sénior
![]() ![]() Marius NituIngénieur développement logiciels Inscription : octobre 2007 Messages : 3 311 ![]() |
Cher Pomalaix,
Restons dans le concret, quelqu’un dit : voilà mes tables, voilà mes indexes, voilà ma volumétrie, voilà mes 3 requêtes (et il doit y avoir au moins 15 encore autres façons d'écrire la requête ...) que est-ce que j’ai dois choisir et vous me faite la théorie du Sant Graal. Moi je vois une requête basique est-ce qu’elle est complexe pour vous ? J’ai la même question pour vous : dans ce cas qu’est-ce que vous nous recommandez ? |
|
|
00
|
|
|
#14 | |
|
Membre expérimenté
![]() Mohamed HouriInscription : mars 2010 Messages : 286 ![]() |
Pomalaix,
C'est bien écrit. C'est bien résumé. Citation:
A un degré près que le CBO est honnête et que le chauffeur de taxi peut ne pas l'être |
|
|
|
02
|
|
|
#15 |
|
Expert Confirmé Sénior
![]() ![]() Marius NituIngénieur développement logiciels Inscription : octobre 2007 Messages : 3 311 ![]() |
Voilà, après la trace c’est maintenant la parabole des chauffeurs de taxi qui nous éclaira sur le sujet !
|
|
|
12
|
|
|
#16 |
|
Membre expérimenté
![]() Mohamed HouriInscription : mars 2010 Messages : 286 ![]() |
Pourtant elle ne vient pas de moi. Elle vient de quelqu'un que vous connaissez très bien et que vous appreciez enormément, j'en suis sûr.
|
|
|
01
|
|
|
#17 | |
|
Membre expérimenté
![]() Mohamed HouriInscription : mars 2010 Messages : 286 ![]() |
Citation:
Et voila la parabole de la fille en retard à l'école pour nous éclairer sur le sujet des indexes et des tables?? |
|
|
|
00
|
|
|
#18 |
|
Expert Confirmé Sénior
![]() ![]() Marius NituIngénieur développement logiciels Inscription : octobre 2007 Messages : 3 311 ![]() |
|
|
|
01
|
|
|
#19 | ||
![]() Inscription : décembre 2002 Messages : 2 387 ![]() |
Citation:
Citation:
Quant au saint Graal, il s'impose d'évidence dès lors que tu dis qu'il faut écrire la (bonne) requête de manière proactive. Le petit bémol, c'est que tu oublies juste de proposer une solution !
__________________
Consultant / formateur Oracle indépendant Certifié OCP 10g et 11g, sécurité 11g |
||
|
|
00
|
|
|
#20 |
|
Membre Expert
![]() Sylvain DevidalChef de projets Générix Inscription : février 2010 Messages : 1 062 ![]() |
Ben moi qui m'attendait à ne pas avoir de réponse, ou une petite règle générale du genre "celle que tous tes collègues arrivent à relire", me voilà bien avancé
Le débat est tout à fait intéressant. Pour en revenir à mes moutons, sachez que vous pouvez autant débattre que vous le voulez, finalement, mon problème ne se pose plus... En avançant dans la mise en place de ma solution, j'ai dû passer par une bête jointure (sans distinct, ni exist ni rien) dans une vue, et c'est les critères appliqués sur la vue qui font le travail. Non seulement le temps de réponse est raisonnable, mais en plus, l'optimisation du plan d'exécution ne se pose plus : les critères appliqués sur la vue sont dynamiques, et j'ai pu constater que le plan d'exécution était parfois très différent (dans certains cas, on commence par un full scan dans la table CNP -assez lent- et dans d'autres cas, on commence par un scan unique index dans CNT, ce qui est on ne peut plus rapide). |
|
|
00
|
Copyright © 2000-2012 - www.developpez.com