2009-08-07 8 views
1

J'ai toujours pensé qu'un nœud dans un plan d'exécution ne peut être exécuté qu'après l'exécution de ses enfants, et donc le coût total d'un nœud doit être supérieur ou égal au coût des nœuds enfants. Cependant, ce n'est pas toujours le cas, comme dans l'exemple suivant:Comment un nœud dans un plan d'exécution peut-il avoir des coûts inférieurs à ceux de son enfant?

Plan hash value: 2810258729 

------------------------------------------------------------------------------------------------- ------------------------ 
| Id | Operation        | Name       | Rows | Bytes | Cost (%CPU)| Time  | 
------------------------------------------------------------------------------------------------- ------------------------ 
| 0 | SELECT STATEMENT       |        | 10 | 1170 | 3871 (1)| 00:00:47 | 
|* 1 | COUNT STOPKEY       |        |  |  |   |   | 
| 2 | VIEW         |        | 10 | 1170 | 3871 (1)| 00:00:47 | 
| 3 | VIEW         | V_TOP_GENRE     | 10 | 1170 | 3871 (1)| 00:00:47 | 
| 4 |  WINDOW SORT       |        | 10 | 890 | 3871 (1)| 00:00:47 | 
| 5 |  MERGE JOIN       |        | 10 | 890 | 3871 (1)| 00:00:47 | 
| 6 |  VIEW        |        | 345 | 10350 | 3867 (1)| 00:00:47 | 
| 7 |  SORT GROUP BY      |        | 345 | 16560 | 133K (1)| 00:26:41 | 
|* 8 |   HASH JOIN      |        | 9627 | 451K| 133K (1)| 00:26:41 | 
| 9 |   VIEW       |        | 9627 | 366K| 133K (1)| 00:26:41 | 
| 10 |   SORT UNIQUE     |        | 9627 | 611K| 133K (51)| 00:26:41 | 
| 11 |   UNION-ALL      |        |  |  |   |   | 
|* 12 |    HASH JOIN     |        | 6639 | 421K| 66681 (1)| 00:13:21 | 
| 13 |    INDEX FAST FULL SCAN  | T_CREATIVE_SELECTED_ADV_CREA | 28973 | 169K|  9 (0)| 00:00:01 | 
| 14 |    NESTED LOOPS    |        | 22243 | 1281K| 66671 (1)| 00:13:21 | 
| 15 |    TABLE ACCESS BY INDEX ROWID| REPORT_FILTER_TIMERANGE  |  1 | 24 |  1 (0)| 00:00:01 | 
|* 16 |    INDEX UNIQUE SCAN   | SYS_C0053942     |  1 |  |  1 (0)| 00:00:01 | 
|* 17 |    TABLE ACCESS FULL   | INSERTION_TV_RADIO   | 22243 | 760K| 66670 (1)| 00:13:21 | 
|* 18 |    HASH JOIN     |        | 2988 | 189K| 66697 (1)| 00:13:21 | 
| 19 |    INDEX FAST FULL SCAN  | T_CREATIVE_SELECTED_ADV_CREA | 28973 | 169K|  9 (0)| 00:00:01 | 
| 20 |    NESTED LOOPS    |        | 10010 | 576K| 66688 (1)| 00:13:21 | 
| 21 |    TABLE ACCESS BY INDEX ROWID| REPORT_FILTER_TIMERANGE  |  1 | 24 |  1 (0)| 00:00:01 | 
|* 22 |    INDEX UNIQUE SCAN   | SYS_C0053942     |  1 |  |  1 (0)| 00:00:01 | 
|* 23 |    TABLE ACCESS FULL   | INSERTION_TV_RADIO   | 10010 | 342K| 66687 (1)| 00:13:21 | 
| 24 |   TABLE ACCESS FULL    | ASSIGNMENT_BROADCAST_GENRE | 25135 | 220K| 20 (0)| 00:00:01 | 
|* 25 |  SORT JOIN       |        | 345 | 10005 |  4 (25)| 00:00:01 | 
| 26 |  TABLE ACCESS FULL     | GENRE      | 345 | 10005 |  3 (0)| 00:00:01 | 
------------------------------------------------------------------------------------------------- ------------------------ 


Predicate Information (identified by operation id): 
--------------------------------------------------- 

    1 - filter(ROWNUM<=10) 
    8 - access("A"."BROADCAST_ID"="C"."BROADCAST_ID") 
    12 - access("AD"."CREATIVE_ID"="A"."CREATIVE_ID") 
    16 - access("B"."RANGE_NAME"='current') 
    17 - filter("A"."BROADCAST_BEFORE_ID"<>(-1) AND "A"."INS_DATE">="B"."START_DATE" AND 
       "A"."INS_DATE"<="B"."END_DATE") 
    18 - access("AD"."CREATIVE_ID"="A"."CREATIVE_ID") 
    22 - access("B"."RANGE_NAME"='current') 
    23 - filter("A"."BROADCAST_AFTER_ID"<>(-1) AND "A"."BROADCAST_BEFORE_ID"<>(-1) AND 
       "A"."BROADCAST_BEFORE_ID"<>"A"."BROADCAST_AFTER_ID" AND "A"."INS_DATE">="B"."START_ DATE" AND "A"."INS_DATE"<="B"."END_DATE") 
    25 - access("TA"."GENRE_ID"="G"."GENRE_ID") 
     filter("TA"."GENRE_ID"="G"."GENRE_ID") 

Quelle est la bonne façon de lire la différence de coûts entre la ligne 6 et 7?

+2

À moins que je manque quelque chose, ne devrait pas le titre de cette question est « Comment un noeud dans un plan d'exécution ont des coûts plus élevés que son parent? " –

+0

@Neil: Vous avez raison, bien sûr. J'ai changé de parent pour enfant, donc ça devrait avoir du sens, maintenant. –

+0

Ce comportement est attendu. C'est une limitation de EXPLAIN PLAN, ce n'est pas un problème. Si vous avez besoin d'informations détaillées sur les performances réelles de l'instruction et comment l'optimiseur sélectionne le plan, tracez les événements 10046 et 10053. – spencer7593

Répondre

3

Vous n'avez pas fourni le SQL, mais vous avez probablement des sous-requêtes scalaires dans la requête globale - EXPLAIN PLAN affiche le coût d'une seule exécution de la sous-requête dans ce cas, mais ne sait pas combien de fois il exécutera .

[Modifier] je me suis dit si je regardais je trouverais une référence Lewis Jonathan qui explique ce mieux - voir http://jonathanlewis.wordpress.com/2007/10/12/scalar-subqueries/

+0

Si je vous comprends bien (et l'article que vous avez lié), l'optimiseur suppose qu'une branche du plan d'exécution sera exécutée 0 fois, et ignore donc les coûts de cette branche. N'est-ce pas une supposition tout à fait dangereuse? –

+1

Je pense qu'il s'agit plus d'un cas où EXPLAIN PLAN ne représente pas fidèlement ce que l'optimiseur utilise pour un processus de décision - une trace 10053 est le meilleur moyen d'en voir les détails. – dpbradley

-1

Peut-être essayer un autre outil (TOAD/SQL * Plus/etc) pour voir si le résultat est le même (c'est-à-dire pour déterminer s'il s'agit d'un problème client ou serveur)?

Toutes vos tables sont-elles ANALYSÉES?

+0

J'ai essayé SQL * Plus, SQL Developer et Aqua Data Studio, tous affichent les mêmes résultats . Les tables sont analysées. –