Chinaunix首页 | 论坛 | 博客
  • 博客访问: 539909
  • 博文数量: 128
  • 博客积分: 4000
  • 博客等级: 上校
  • 技术积分: 1345
  • 用 户 组: 普通用户
  • 注册时间: 2008-01-22 21:43
文章分类

全部博文(128)

文章存档

2009年(30)

2008年(98)

我的朋友

分类: Oracle

2008-10-17 16:34:57

今天一同事说,在where条件下>= 执行得很快,<=执行得很慢
语句如下:

select connector_id,
             conn.sidea_port_id,
             conn.sideb_port_id,
             conn.rsc_spec_id as line_rsc_spec_id,
               PG_TRP_FUNCTION.Fun_GetCodeByPortAndSpec(1,
                                                        conn.sidea_port_id,
                                                        conn.sidea_port_spec_id) as up_dev_code,
               PG_TRP_FUNCTION.Fun_GetCodeByPortAndSpec(2,
                                                        conn.sidea_port_id,
                                                        conn.sidea_port_spec_id) as up_port_code,
               cab.code as cable_code,
               conn.code as line_code,
               PG_TRP_FUNCTION.Fun_GetCodeByPortAndSpec(1,
                                                        conn.sideb_port_id,
                                                        conn.sideb_port_spec_id) as down_dev_code,
               PG_TRP_FUNCTION.Fun_GetCodeByPortAndSpec(2,
                                                        conn.sideb_port_id,
                                                        conn.sideb_port_spec_id) as down_port_code,
             PG_TRP_FUNCTION.Fun_GetDevIdByPortAndSpec(CONN.SIDEA_PORT_ID,
                                                     CONN.SIDEA_PORT_SPEC_ID) AS UP_DEVICE_ID,
                  PG_TRP_FUNCTION.Fun_GetDevIdByPortAndSpec(CONN.SIDEB_PORT_ID,
                                                     CONN.SIDEB_PORT_SPEC_ID) AS DOWN_DEVICE_ID,
                   PG_TRP_FUNCTION.Fun_GetDevSpecIdByPortAndSpec(conn.sidea_port_id,
                                                         conn.sidea_port_spec_id) as up_dev_rsc_spec_id,
                  PG_TRP_FUNCTION.Fun_GetDevSpecIdByPortAndSpec(conn.sideb_port_id,
                                                         conn.sideb_port_spec_id) as down_dev_rsc_spec_id     
          from connector conn, device cab, user_side_port usp
         where conn.device_id = cab.device_id     
           and conn.sidea_port_id = usp.port_id
           and conn.rsc_status_cd = 1
           and conn.side_id in
               (select side_id
                  from side
                 where node_id_a in
                       (select nd.node_id
                          from device dev, node nd
                         where dev.device_id = nd.device_id
                           and dev.rsc_spec_id in (10301001, 10301002, 10301003)
                           and dev.code like '79G/J0010101%'
                           and dev.area_id = 18 ))
       and usp.code >= '0017'
        and rownum < 20 ;

####################################
# and usp.code >= '0017'的执行计划:#
###################################
SELECT STATEMENT, GOAL = CHOOSE            1018    19    1881    1018
 COUNT STOPKEY                       
  NESTED LOOPS            1018    64    6336    1018
   NESTED LOOPS            890    64    5504    890
    NESTED LOOPS            762    64    4416    762
     NESTED LOOPS            31    43    946    31
      VIEW    SYS    VW_NSO_1    6    1    13   
       SORT UNIQUE                1    34   
        NESTED LOOPS            6    1    34    6
         TABLE ACCESS BY INDEX ROWID    RM    DEVICE    4    1    24    4
          INDEX RANGE SCAN    RM    UIDX_DEV_CODE    3    1        3
         TABLE ACCESS BY INDEX ROWID    RM    NODE    2    1    10    2
          INDEX UNIQUE SCAN    RM    UIDX_NODE_DEVICE    1    1        1
      TABLE ACCESS BY INDEX ROWID    RM    SIDE    23    43    387    23
       INDEX RANGE SCAN    RM    UIDX_SIDE_NODEA    2    43        2
     TABLE ACCESS BY INDEX ROWID    RM    CONNECTOR    17    1    47    17
      INDEX RANGE SCAN    RM    IDX_CONNECTOR_SIDE    2    33        2
    TABLE ACCESS BY INDEX ROWID    RM    DEVICE    2    1    17    2
     INDEX UNIQUE SCAN    RM    PK_DEVICE    1    1        1
   TABLE ACCESS BY INDEX ROWID    RM    USER_SIDE_PORT    2    1    13    2
    INDEX UNIQUE SCAN    RM    PK_USER_SIDE_PORT    1    1        1

####################################
# and usp.code <= '0017'的执行计划:#
###################################
SELECT STATEMENT, GOAL = CHOOSE            769    1    99    769
 COUNT STOPKEY                       
  NESTED LOOPS            769    1    99    769
   HASH JOIN            767    1    82    767
    TABLE ACCESS BY INDEX ROWID    RM    CONNECTOR    17    1    47    17
     NESTED LOOPS            762    64    4416    762
      NESTED LOOPS            31    43    946    31
       VIEW    SYS    VW_NSO_1    6    1    13   
        SORT UNIQUE                1    34   
         NESTED LOOPS            6    1    34    6
          TABLE ACCESS BY INDEX ROWID    RM    DEVICE    4    1    24    4
           INDEX RANGE SCAN    RM    UIDX_DEV_CODE    3    1        3
          TABLE ACCESS BY INDEX ROWID    RM    NODE    2    1    10    2
           INDEX UNIQUE SCAN    RM    UIDX_NODE_DEVICE    1    1        1
       TABLE ACCESS BY INDEX ROWID    RM    SIDE    23    43    387    23
        INDEX RANGE SCAN    RM    UIDX_SIDE_NODEA    2    43        2
      INDEX RANGE SCAN    RM    IDX_CONNECTOR_SIDE    2    33        2
    TABLE ACCESS BY INDEX ROWID    RM    USER_SIDE_PORT    4    11149    144937    4
     INDEX RANGE SCAN    RM    UIDX_USP_CODE    2    1        2
   TABLE ACCESS BY INDEX ROWID    RM    DEVICE    2    1    17    2
    INDEX UNIQUE SCAN    RM    PK_DEVICE    1    1        1

很明显>= 走的是嵌套, <= 走的HASH JOIN
加上暗示
/*+USE_NL(conn, cab, usp) */

-----------------------------------------------------------------
然后同事继续提:
小小修改一下where条件
       and usp.code <= '0017'
       and usp.code >= '0014'
当数值不同时,执行很快,当数值相同时,执行相当慢

继续看执行计划,这次是带/*+USE_NL(conn, cab, usp) */的执行计划

当执行:
       and usp.code <= '0017'
       and usp.code >= '0014'
执行计划:
SELECT STATEMENT, GOAL = CHOOSE            1018    19    1881    1018         SELE
 COUNT STOPKEY                                                                COU
  NESTED LOOPS            1018    64    6336    1018                           NE
   NESTED LOOPS            890    64    5504    890                               N
    NESTED LOOPS            762    64    4416    762                             
     NESTED LOOPS            31    43    946    31                                
      VIEW    SYS    VW_NSO_1    6    1    13                                      
       SORT UNIQUE                1    34                                        
        NESTED LOOPS            6    1    34    6                                 
         TABLE ACCESS BY INDEX ROWID    RM    DEVICE    4    1    24    4         
          INDEX RANGE SCAN    RM    UIDX_DEV_CODE    3    1        3               
         TABLE ACCESS BY INDEX ROWID    RM    NODE    2    1    10    2           
          INDEX UNIQUE SCAN    RM    UIDX_NODE_DEVICE    1    1        1           
      TABLE ACCESS BY INDEX ROWID    RM    SIDE    23    43    387    23          
       INDEX RANGE SCAN    RM    UIDX_SIDE_NODEA    2    43        2               
     TABLE ACCESS BY INDEX ROWID    RM    CONNECTOR    17    1    47    17        
      INDEX RANGE SCAN    RM    IDX_CONNECTOR_SIDE    2    33        2           
    TABLE ACCESS BY INDEX ROWID    RM    DEVICE    2    1    17    2               
     INDEX UNIQUE SCAN    RM    PK_DEVICE    1    1        1                       
   TABLE ACCESS BY INDEX ROWID    RM    USER_SIDE_PORT    2    1    13    2       T
    INDEX UNIQUE SCAN    RM    PK_USER_SIDE_PORT    1    1        1                 


当执行:
       and usp.code <= '0017'
       and usp.code >= '0017'
执行计划
SELECT STATEMENT, GOAL = CHOOSE            332    1    99    332
 COUNT STOPKEY                       
  NESTED LOOPS            332    1    99    332
   NESTED LOOPS            330    1    82    330
    NESTED LOOPS            202    64    4672    202
     NESTED LOOPS            10    64    1664    10
      VIEW    SYS    VW_NSO_1    6    1    13   
       SORT UNIQUE                1    34   
        NESTED LOOPS            6    1    34    6
         TABLE ACCESS BY INDEX ROWID    RM    DEVICE    4    1    24    4
          INDEX RANGE SCAN    RM    UIDX_DEV_CODE    3    1        3
         TABLE ACCESS BY INDEX ROWID    RM    NODE    2    1    10    2
          INDEX UNIQUE SCAN    RM    UIDX_NODE_DEVICE    1    1        1
      TABLE ACCESS BY INDEX ROWID    RM    USER_SIDE_PORT    2    64    832    2
       INDEX RANGE SCAN    RM    UIDX_USP_CODE    1    64        1
     TABLE ACCESS BY INDEX ROWID    RM    CONNECTOR    3    1    47    3
      INDEX RANGE SCAN    RM    IDX_CONNECTOR_PORTA    2    1        2
    TABLE ACCESS BY INDEX ROWID    RM    SIDE    2    1    9    2
     INDEX UNIQUE SCAN    RM    PK_SIDE    1    1        1
   TABLE ACCESS BY INDEX ROWID    RM    DEVICE    2    1    17    2
    INDEX UNIQUE SCAN    RM    PK_DEVICE    1    1        1

看到表连接的顺序不同

解决方法,使用/*+ORDERED*/

调优后的SQL语句:
select /*+USE_NL(conn, cab, usp) ORDERED*/ connector_id,
             conn.sidea_port_id,
             conn.sideb_port_id,
             conn.rsc_spec_id as line_rsc_spec_id,
               PG_TRP_FUNCTION.Fun_GetCodeByPortAndSpec(1,
                                                        conn.sidea_port_id,
                                                        conn.sidea_port_spec_id) as up_dev_code,
               PG_TRP_FUNCTION.Fun_GetCodeByPortAndSpec(2,
                                                        conn.sidea_port_id,
                                                        conn.sidea_port_spec_id) as up_port_code,
               cab.code as cable_code,
               conn.code as line_code,
               PG_TRP_FUNCTION.Fun_GetCodeByPortAndSpec(1,
                                                        conn.sideb_port_id,
                                                        conn.sideb_port_spec_id) as down_dev_code,
               PG_TRP_FUNCTION.Fun_GetCodeByPortAndSpec(2,
                                                        conn.sideb_port_id,
                                                        conn.sideb_port_spec_id) as down_port_code,
             PG_TRP_FUNCTION.Fun_GetDevIdByPortAndSpec(CONN.SIDEA_PORT_ID,
                                                     CONN.SIDEA_PORT_SPEC_ID) AS UP_DEVICE_ID,
                  PG_TRP_FUNCTION.Fun_GetDevIdByPortAndSpec(CONN.SIDEB_PORT_ID,
                                                     CONN.SIDEB_PORT_SPEC_ID) AS DOWN_DEVICE_ID,
                   PG_TRP_FUNCTION.Fun_GetDevSpecIdByPortAndSpec(conn.sidea_port_id,
                                                         conn.sidea_port_spec_id) as up_dev_rsc_spec_id,
                  PG_TRP_FUNCTION.Fun_GetDevSpecIdByPortAndSpec(conn.sideb_port_id,
                                                         conn.sideb_port_spec_id) as down_dev_rsc_spec_id     
          from connector conn, device cab, user_side_port usp
         where conn.device_id = cab.device_id     
           and conn.sidea_port_id = usp.port_id
           and conn.rsc_status_cd = 1
           and conn.side_id in
               (select side_id
                  from side
                 where node_id_a in
                       (select nd.node_id
                          from device dev, node nd
                         where dev.device_id = nd.device_id
                           and dev.rsc_spec_id in (10301001, 10301002, 10301003)
                           and dev.code like '79G/J0010101%'
                           and dev.area_id = 18 ))
       and usp.code >= '0017'
       and usp.code <= '0017'
        and rownum < 20 ;

阅读(1638) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~