• OR导致笛卡尔积


    近期监控数据库,发现以下语句跑得很慢,原来运行计划走了导致笛卡尔积,来看以下语句:

    SQL> explain plan for
      2  SELECT COUNT(*)
      3    FROM "GD_FS"."TZZ_SJ_DEV_DISC_79073" "A2",
      4         "GD_FS"."TZZ_SJ_DEVELOP_MONTH"  "A1"
      5   WHERE "A1"."SERV_ID" = "A2"."SERV_ID"
      6     AND "A1"."STAT_DATE" = "A2"."STAT_DATE"
      7     AND "A2"."ALLO_DISC_TYPE_3" LIKE '%租机%'
      8      OR "A2"."ALLO_DISC_TYPE_3" LIKE '%零预存%';
    
    Explained.
    
    SQL> @getplan
    'general,outline,starts'
    
    Enter value for plan type:
    
    PLAN_TABLE_OUTPUT
    ---------------------------------------------------------------------------------------------------------------------
    
    Plan hash value: 1410945947
    
    ------------------------------------------------------------------------------------------------
    | Id  | Operation              | Name                  | Rows  | Bytes | Cost (%CPU)| Time     |
    ------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT       |                       |     1 |    42 |   271M  (2)|999:59:59 |
    |   1 |  SORT AGGREGATE        |                       |     1 |    42 |            |          |
    |   2 |   CONCATENATION        |                       |       |       |            |          |
    |   3 |    MERGE JOIN CARTESIAN|                       |    82G|  3239G|   271M  (2)|999:59:59 |
    |*  4 |     TABLE ACCESS FULL  | TZZ_SJ_DEV_DISC_79073 | 22606 |   640K|   743   (2)| 00:00:11 |
    |   5 |     BUFFER SORT        |                       |  3663K|    45M|   271M  (2)|999:59:59 |
    |   6 |      TABLE ACCESS FULL | TZZ_SJ_DEVELOP_MONTH  |  3663K|    45M| 11994   (2)| 00:02:48 |
    |*  7 |    HASH JOIN           |                       |     1 |    42 | 12762   (2)| 00:02:59 |
    |*  8 |     TABLE ACCESS FULL  | TZZ_SJ_DEV_DISC_79073 | 21476 |   608K|   743   (2)| 00:00:11 |
    |   9 |     TABLE ACCESS FULL  | TZZ_SJ_DEVELOP_MONTH  |  3663K|    45M| 11996   (2)| 00:02:48 |
    ------------------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       4 - filter("A2"."ALLO_DISC_TYPE_3" LIKE '%零预存%')
       7 - access("A1"."SERV_ID"="A2"."SERV_ID" AND "A1"."STAT_DATE"="A2"."STAT_DATE")
       8 - filter("A2"."ALLO_DISC_TYPE_3" LIKE '%租机%' AND LNNVL("A2"."ALLO_DISC_TYPE_3"
                  LIKE '%零预存%'))
    

    --表大小的情况:

    OWNER                SEGMENT_NAME                   SEGMENT_TYPE           Size(Mb)
    -------------------- ------------------------------ -------------------- ----------
    GD_FS                TZZ_SJ_DEV_DISC_79073          TABLE                        43
    GD_FS                TZZ_SJ_DEVELOP_MONTH           TABLE                   577.375

    两个表并不大,一个43M,一个577M,这里肯定是开发者不小心,写错了语句,导致跑不出来。
    AND "A2"."ALLO_DISC_TYPE_3" LIKE '%租机%'  OR "A2"."ALLO_DISC_TYPE_3" LIKE '%零预存%';改成
    AND ("A2"."ALLO_DISC_TYPE_3" LIKE '%租机%'  OR "A2"."ALLO_DISC_TYPE_3" LIKE '%零预存%');
    改动语句后,问题解决。


    改写后:

    SQL> explain plan for
      2  SELECT COUNT(*)
      3    FROM "GD_FS"."TZZ_SJ_DEV_DISC_79073" "A2",
      4         "GD_FS"."TZZ_SJ_DEVELOP_MONTH"  "A1"
      5   WHERE "A1"."SERV_ID" = "A2"."SERV_ID"
      6     AND "A1"."STAT_DATE" = "A2"."STAT_DATE"
      7     AND ("A2"."ALLO_DISC_TYPE_3" LIKE '%租机%' OR "A2"."ALLO_DISC_TYPE_3" LIKE '%零预存%');
    
    Explained.
    
    SQL> @getplan
    'general,outline,starts'
    
    Enter value for plan type:
    
    PLAN_TABLE_OUTPUT
    --------------------------------------------------------------------------------------------------------
    
    Plan hash value: 3104770780
    
    ---------------------------------------------------------------------------------------------
    | Id  | Operation           | Name                  | Rows  | Bytes | Cost (%CPU)| Time     |
    ---------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT    |                       |     1 |    42 | 12765   (2)| 00:02:59 |
    |   1 |  SORT AGGREGATE     |                       |     1 |    42 |            |          |
    |*  2 |   HASH JOIN         |                       | 44081 |  1808K| 12765   (2)| 00:02:59 |
    |*  3 |    TABLE ACCESS FULL| TZZ_SJ_DEV_DISC_79073 | 44081 |  1248K|   745   (3)| 00:00:11 |
    |   4 |    TABLE ACCESS FULL| TZZ_SJ_DEVELOP_MONTH  |  3663K|    45M| 11996   (2)| 00:02:48 |
    ---------------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       2 - access("A1"."SERV_ID"="A2"."SERV_ID" AND "A1"."STAT_DATE"="A2"."STAT_DATE")
       3 - filter("A2"."ALLO_DISC_TYPE_3" LIKE '%租机%' OR "A2"."ALLO_DISC_TYPE_3" LIKE
                  '%零预存%')
    



  • 相关阅读:
    MYSQL中数据类型介绍
    怎么评估软件上线标准
    文件安全复制之 FastCopy
    强烈推荐美文之《从此刻起,我要》
    浅谈软件测试与墨菲定律
    夜神模拟器--安卓模拟神器
    RoadMap:如何创建产品路线图
    利用Python爬虫刷店铺微博等访问量最简单有效教程
    MySQL 数据库中删除重复数据的方法
    如何测试一个杯子
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/4296900.html
Copyright © 2020-2023  润新知