HelloDBA  
搜索WWW 搜索 HelloDBABA
首页 技术文档 培训教程 案例分析 工具、书籍 数据库新闻 网摘 Blog 收藏
Oracle技术站。提供各种数据库技术文档、培训教程、解决方案、案例、工具及周边新闻。同时,本站还提供oracle培训、优化、备份方案和技术支持。email: fuyuncat@gmail.com  MSN: fuyuncat@hotmail.com

 


NULL IS NOT NULL in execution plan

作者: fuyuncat

来源: www.HelloDBA.com

    I get a SQL from a developer today, he was confused by its execution plan output.
 

SQL代码
  1. HELLODBA.COM> explain plan for  
  2.   2  SELECT MAX(CNTR_MVMT_ID)   
  3.   3                         FROM CS2_CT_MVMT MVMT   
  4.   4                        WHERE MVMT.CNTR_NUM = :P_CNTR_NUM   
  5.   5                          AND MVMT.SP_COMPANY_ID = :P_SVC_PRD_ID   
  6.   6                          AND NVL(MVMT.EVENT_CURRENT_CONTRA_IND,'0')='DELETED'  
  7.   7                          AND NVL(MVMT.EVENT_CURRENT_CONTRA_IND,'0')= 'ROLLBACK'  
  8.   8                           AND exists   
  9.   9                           (select 1 from standard_event_label s where s.event_code= mvmt.event_cs_cde   
  10.  10                            and nvl(s.dimension_type, '0')= nvl(mvmt.event_cs_dimension_tp,'0')   
  11.  11                            and nvl(mvmt.event_cs_dimension_vl,'0')=nvl(s.dimension_value,'0')   
  12.  12                            and mvmt.event_cs_est_actual_ind= s.est_actual_indicator   
  13.  13                            and s.is_display='1')   
  14.  14                            and exists(select 1 from cs2_ct_bl_info ctbl where ctbl.cntr_mvmt_id=mvmt.cntr_mvmt_id   
  15.  15                            and ctbl.bl_num='NGBLAX021099');   
  16.   
  17. Explained.   
  18.   
  19. SQL> select * from table(dbms_xplan.display());   
  20.   
  21. PLAN_TABLE_OUTPUT   
  22. ---------------------------------------------------------------------------------------------------------------------   
  23. Plan hash value: 2642346965   
  24.   
  25. --------------------------------------------------------------------------------------------------------------   
  26. | Id  | Operation                         | Name                     | Rows  | Bytes | Cost (%CPU)| Time     |   
  27. --------------------------------------------------------------------------------------------------------------   
  28. |   0 | SELECT STATEMENT                  |                          |     1 |   156 |     0   (0)|       |   
  29. |   1 |  SORT AGGREGATE                   |                          |     1 |   156 |            |       |   
  30. |*  2 |   FILTER                          |                          |       |       |            |       |   
  31. |*  3 |    HASH JOIN SEMI                 |                          |     1 |   156 |   100   (2)| 00:00:02 |   
  32. |*  4 |     TABLE ACCESS BY INDEX ROWID   | CS2_CT_MVMT              |     1 |   109 |     2   (0)| 00:00:01 |   
  33. |   5 |      NESTED LOOPS                 |                          |    35 |  4445 |    97   (2)| 00:00:02 |   
  34. |   6 |       SORT UNIQUE                 |                          |    63 |  1134 |    63   (0)| 00:00:01 |   
  35. |   7 |        TABLE ACCESS BY INDEX ROWID| CS2_CT_BL_INFO           |    63 |  1134 |    63   (0)| 00:00:01 |   
  36. |*  8 |         INDEX RANGE SCAN          | CS2_CT_BL_INFO_IDX2      |    63 |       |     4   (0)| 00:00:01 |   
  37. |*  9 |       INDEX RANGE SCAN            | CS2_CT_MVMT_PK1          |     1 |       |     1   (0)| 00:00:01 |   
  38. |* 10 |     TABLE ACCESS BY INDEX ROWID   | STANDARD_EVENT_LABEL     |    48 |  1392 |     2   (0)| 00:00:01 |   
  39. |* 11 |      INDEX FULL SCAN              | STANDARD_EVENT_LABEL_UK1 |    55 |       |     1   (0)| 00:00:01 |   
  40. --------------------------------------------------------------------------------------------------------------   
  41.   
  42. Predicate Information (identified by operation id):   
  43. ---------------------------------------------------   
  44.   
  45.    2 - filter(NULL IS NOT NULL)   
  46.    3 - access("S"."EVENT_CODE"="MVMT"."EVENT_CS_CDE" AND  
  47.               NVL("S"."DIMENSION_TYPE",'0')=NVL("MVMT"."EVENT_CS_DIMENSION_TP",'0'AND  
  48.               NVL("MVMT"."EVENT_CS_DIMENSION_VL",'0')=NVL("S"."DIMENSION_VALUE",'0'AND  
  49.               "MVMT"."EVENT_CS_EST_ACTUAL_IND"="S"."EST_ACTUAL_INDICATOR")   
  50.    4 - filter("MVMT"."CNTR_NUM"=:P_CNTR_NUM AND "MVMT"."SP_COMPANY_ID"=:P_SVC_PRD_ID AND  
  51.               ("MVMT"."EVENT_CS_EST_ACTUAL_IND"='A' OR "MVMT"."EVENT_CS_EST_ACTUAL_IND"='E' OR  
  52.               "MVMT"."EVENT_CS_EST_ACTUAL_IND"='N'AND NVL("MVMT"."EVENT_CURRENT_CONTRA_IND",'0')='DELETED')   
  53.    8 - access("CTBL"."BL_NUM"='NGBLAX021099')   
  54.    9 - access("CTBL"."CNTR_MVMT_ID"="MVMT"."CNTR_MVMT_ID")   
  55.   10 - filter("S"."IS_DISPLAY"=1)   
  56.   11 - filter("S"."EST_ACTUAL_INDICATOR" IS NOT NULL)   

    He was confused by the cost of the plan. Eventhough the cost of the sub plan tree is 100, the final cost is 0.
 

    Look into the output, the 2nd filter in the predicate information, NULL IS NOT NULL. It's added by the optimizer automaticly. We know NULL IS NOT NULL is means always FALSE. Optimzier will add such filter when it found the logic result of the sub plan tree is FALSE, it will cause to the plan tree will never be executed. So, no matter how much cost of the plan tree, it will become 0 with this filter.
 

    When find such filter added by optimizer, it's normally means a logic problem in the SQL. Review the SQL, we can find the logic defect quickly:
 

SQL代码
  1. 6                          AND NVL(MVMT.EVENT_CURRENT_CONTRA_IND,'0')='DELETED'  
  2. 7                          AND NVL(MVMT.EVENT_CURRENT_CONTRA_IND,'0')= 'ROLLBACK'  

    This means 'DELETED'='ROLLBACK', impossible. Double check with the developer, it's his typo. The "=" should be "!=".
 

    --- Fuyuncat ---

 

Top

Copyright @2005 HelloDBA.Com All reseverd.

申明
by fuyuncat