zoukankan      html  css  js  c++  java
  • 利用Merge代替复杂的UPDATE语句

    有朋友问我一个update语句,下面两种写法哪个性能更高,一个是没HINT的,一个是有HINT的

    UPDATE CS_PERFORMANCE_CURRENT C
       SET C.PERFORMANCE_SCORE = '0.00', C.ASSESS_DESC = '劳动纪律考核'
     WHERE C.TARGET_MODE_SEQ_ID =
           (SELECT D.SEQ_ID
              FROM CS_TARGET_MODEL_REL D, CS_AREA A
             WHERE D.ASSESS_ID = 1265
               AND C.TARGET_MODE_SEQ_ID = D.SEQ_ID
               AND D.STAFF_ID = 8
               AND C.COM_DATE = TO_DATE('20110801','YYYYMMDD')
               AND D.TARGET_MODEL_ID = 332
               AND D.STATE = TO_CHAR(2)
               AND D.AREA_ID = A.AREA_ID
               AND A.AREA_NAME = '永兴支局');
    
    Plan hash value: 2321634139
     
    ----------------------------------------------------------------------------------------------------------
    | Id  | Operation                       | Name                   | Rows  | Bytes | Cost (%CPU)| Time     |
    ----------------------------------------------------------------------------------------------------------
    |   0 | UPDATE STATEMENT                |                        |     1 |    41 |   679   (1)| 00:00:09 |
    |   1 |  UPDATE                         | CS_PERFORMANCE_CURRENT |       |       |            |          |
    |*  2 |   FILTER                        |                        |       |       |            |          |
    |   3 |    TABLE ACCESS FULL            | CS_PERFORMANCE_CURRENT |   124K|  4968K|   664   (1)| 00:00:08 |
    |*  4 |    FILTER                       |                        |       |       |            |          |
    |   5 |     NESTED LOOPS                |                        |     1 |    52 |     3   (0)| 00:00:01 |
    |*  6 |      TABLE ACCESS BY INDEX ROWID| CS_TARGET_MODEL_REL    |     1 |    26 |     2   (0)| 00:00:01 |
    |*  7 |       INDEX UNIQUE SCAN         | PK_CS_TARGET_RULE_REL  |     1 |       |     1   (0)| 00:00:01 |
    |*  8 |      TABLE ACCESS BY INDEX ROWID| CS_AREA                |     1 |    26 |     1   (0)| 00:00:01 |
    |*  9 |       INDEX UNIQUE SCAN         | PK_CS_AREA_NEW         |     1 |       |     0   (0)| 00:00:01 |
    ----------------------------------------------------------------------------------------------------------
     
    Predicate Information (identified by operation id):
    ---------------------------------------------------
     
       2 - filter("C"."TARGET_MODE_SEQ_ID"= (SELECT "D"."SEQ_ID" FROM "CS_AREA" 
                  "A","CS_TARGET_MODEL_REL" "D" WHERE :B1=TO_DATE(' 2011-08-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss') 
                  AND "D"."SEQ_ID"=:B2 AND "D"."STAFF_ID"=8 AND "D"."ASSESS_ID"=1265 AND "D"."TARGET_MODEL_ID"=332 
                  AND "D"."STATE"='2' AND "D"."AREA_ID"="A"."AREA_ID" AND "A"."AREA_NAME"='永兴支局'))
       4 - filter(:B1=TO_DATE(' 2011-08-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss'))
       6 - filter("D"."STAFF_ID"=8 AND "D"."ASSESS_ID"=1265 AND "D"."TARGET_MODEL_ID"=332 AND 
                  "D"."STATE"='2')
       7 - access("D"."SEQ_ID"=:B1)
       8 - filter("A"."AREA_NAME"='永兴支局')
       9 - access("D"."AREA_ID"="A"."AREA_ID")
    
    已用时间:  00: 00: 00.29
    
    统计信息
    ----------------------------------------------------------
              1  recursive calls
              0  db block gets
          32670  consistent gets
             21  physical reads
              0  redo size
            536  bytes sent via SQL*Net to client
            978  bytes received via SQL*Net from client
              3  SQL*Net roundtrips to/from client
              1  sorts (memory)
              0  sorts (disk)
              0  rows processed
    UPDATE /*+ PUSH_SUBQ(@D) */CS_PERFORMANCE_CURRENT C
       SET C.PERFORMANCE_SCORE = '0.00', C.ASSESS_DESC = '劳动纪律考核'
     WHERE C.TARGET_MODE_SEQ_ID =
           (SELECT /*+ QB_NAME(D) */ D.SEQ_ID
              FROM CS_TARGET_MODEL_REL D, CS_AREA A
             WHERE D.ASSESS_ID = 1265
               AND C.TARGET_MODE_SEQ_ID = D.SEQ_ID
               AND D.STAFF_ID = 8
               AND C.COM_DATE = TO_DATE('20110801','YYYYMMDD')
               AND D.TARGET_MODEL_ID = 332
               AND D.STATE = TO_CHAR(2)
               AND D.AREA_ID = A.AREA_ID
               AND A.AREA_NAME = '永兴支局')
               
    Plan hash value: 4189652906
     
    ----------------------------------------------------------------------------------------------------------
    | Id  | Operation                       | Name                   | Rows  | Bytes | Cost (%CPU)| Time     |
    ----------------------------------------------------------------------------------------------------------
    |   0 | UPDATE STATEMENT                |                        |     1 |    39 |    43   (0)| 00:00:01 |
    |   1 |  UPDATE                         | CS_PERFORMANCE_CURRENT |       |       |            |          |
    |*  2 |   TABLE ACCESS FULL             | CS_PERFORMANCE_CURRENT |     1 |    39 |    40   (0)| 00:00:01 |
    |*  3 |    FILTER                       |                        |       |       |            |          |
    |   4 |     NESTED LOOPS                |                        |     1 |    47 |     3   (0)| 00:00:01 |
    |*  5 |      TABLE ACCESS BY INDEX ROWID| CS_TARGET_MODEL_REL    |     1 |    25 |     2   (0)| 00:00:01 |
    |*  6 |       INDEX UNIQUE SCAN         | PK_CS_TARGET_RULE_REL  |     1 |       |     1   (0)| 00:00:01 |
    |*  7 |      TABLE ACCESS BY INDEX ROWID| CS_AREA                |     1 |    22 |     1   (0)| 00:00:01 |
    |*  8 |       INDEX UNIQUE SCAN         | PK_CS_AREA_NEW         |     1 |       |     0   (0)| 00:00:01 |
    ----------------------------------------------------------------------------------------------------------
     
    Predicate Information (identified by operation id):
    ---------------------------------------------------
     
       2 - filter("C"."TARGET_MODE_SEQ_ID"= (SELECT /*+ PUSH_SUBQ QB_NAME ("D") */ "D"."SEQ_ID" FROM 
                  "CS_AREA" "A","CS_TARGET_MODEL_REL" "D" WHERE :B1=TO_DATE(' 2011-08-01 00:00:00', 'syyyy-mm-dd 
                  hh24:mi:ss') AND "D"."SEQ_ID"=:B2 AND "D"."ASSESS_ID"=1265 AND "D"."STAFF_ID"=8 AND 
                  "D"."TARGET_MODEL_ID"=332 AND "D"."STATE"='2' AND "D"."AREA_ID"="A"."AREA_ID" AND 
                  "A"."AREA_NAME"='永兴支局'))
       3 - filter(:B1=TO_DATE(' 2011-08-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss'))
       5 - filter("D"."ASSESS_ID"=1265 AND "D"."STAFF_ID"=8 AND "D"."TARGET_MODEL_ID"=332 AND 
                  "D"."STATE"='2')
       6 - access("D"."SEQ_ID"=:B1)
       7 - filter("A"."AREA_NAME"='永兴支局')
       8 - access("D"."AREA_ID"="A"."AREA_ID")
    
    统计信息
    ----------------------------------------------------------
              1  recursive calls
              0  db block gets
          32670  consistent gets
             21  physical reads
              0  redo size
            536  bytes sent via SQL*Net to client
            978  bytes received via SQL*Net from client
              3  SQL*Net roundtrips to/from client
              1  sorts (memory)
              0  sorts (disk)
              0  rows processed

    可以看到,逻辑读都是一样的,那么这个SQL,加不加HINT性能都一样。其实对于Oracle中的update 语句,如果SQL很复杂,需要关联多个表去做update,这个时候应该用

    merge 语句代替 update,用Merge 改写之后 :

    MERGE INTO CS_PERFORMANCE_CURRENT A
    USING (SELECT D.SEQ_ID
           FROM   CS_TARGET_MODEL_REL D,
                  CS_AREA             M
           WHERE  D.ASSESS_ID = 1265 AND
                  D.STAFF_ID = 8 AND
                  D.TARGET_MODEL_ID = 332 AND
                  D.STATE = TO_CHAR(2) AND
                  D.AREA_ID = M.AREA_ID AND
                  M.AREA_NAME = '永兴支局') H
    ON (A.TARGET_MODE_SEQ_ID = H.SEQ_ID)
    WHEN MATCHED THEN
      UPDATE SET A.PERFORMANCE_SCORE = '0.00', A.ASSESS_DESC = '劳动纪律考核' WHERE A.COM_DATE = TO_DATE('20110801', 'YYYYMMDD');
     
     ----------------------------------------------------------------------------------------------------------
     | Id  | Operation                       | Name                   | Rows  | Bytes | Cost (%CPU)| Time     |
     ----------------------------------------------------------------------------------------------------------
     |   0 | MERGE STATEMENT                 |                        |     1 |   167 |   750   (1)| 00:00:10 |
     |   1 |  MERGE                          | CS_PERFORMANCE_CURRENT |       |       |            |          |
     |   2 |   VIEW                          |                        |       |       |            |          |
     |*  3 |    HASH JOIN                    |                        |     1 |   210 |   750   (1)| 00:00:10 |
     |   4 |     NESTED LOOPS                |                        |     1 |    52 |    85   (2)| 00:00:02 |
     |*  5 |      TABLE ACCESS FULL          | CS_TARGET_MODEL_REL    |     1 |    26 |    84   (2)| 00:00:02 |
     |*  6 |      TABLE ACCESS BY INDEX ROWID| CS_AREA                |     1 |    26 |     1   (0)| 00:00:01 |
     |*  7 |       INDEX UNIQUE SCAN         | PK_CS_AREA_NEW         |     1 |       |     0   (0)| 00:00:01 |
     |   8 |     TABLE ACCESS FULL           | CS_PERFORMANCE_CURRENT |   124K|    18M|   664   (1)| 00:00:08 |
     ----------------------------------------------------------------------------------------------------------
      
     Predicate Information (identified by operation id):
     ---------------------------------------------------
      
        3 - access("A"."TARGET_MODE_SEQ_ID"="D"."SEQ_ID")
        5 - filter("D"."STAFF_ID"=8 AND "D"."ASSESS_ID"=1265 AND "D"."TARGET_MODEL_ID"=332 AND 
                   "D"."STATE"='2')
        6 - filter("M"."AREA_NAME"='永兴支局')
        7 - access("D"."AREA_ID"="M"."AREA_ID")
              
              
    统计信息
    ----------------------------------------------------------
            333  recursive calls
              0  db block gets
           3474  consistent gets
              3  physical reads
              0  redo size
            546  bytes sent via SQL*Net to client
            998  bytes received via SQL*Net from client
              3  SQL*Net roundtrips to/from client
             15  sorts (memory)
              0  sorts (disk)
              0  rows processed          


    逻辑读下降了近10倍,这里 CS_PERFORMANCE_CURRENT 是全表扫描,它有100W的数据量,所以建立索引在TARGET_MODE_SEQ_ID列上

    Plan hash value: 3908453434
     
    -----------------------------------------------------------------------------------------------------------
    | Id  | Operation                        | Name                   | Rows  | Bytes | Cost (%CPU)| Time     |
    -----------------------------------------------------------------------------------------------------------
    |   0 | MERGE STATEMENT                  |                        |     1 |   167 |    88   (2)| 00:00:02 |
    |   1 |  MERGE                           | CS_PERFORMANCE_CURRENT |       |       |            |          |
    |   2 |   VIEW                           |                        |       |       |            |          |
    |   3 |    TABLE ACCESS BY INDEX ROWID   | CS_PERFORMANCE_CURRENT |     1 |   158 |     3   (0)| 00:00:01 |
    |   4 |     NESTED LOOPS                 |                        |     1 |   210 |    88   (2)| 00:00:02 |
    |   5 |      NESTED LOOPS                |                        |     1 |    52 |    85   (2)| 00:00:02 |
    |*  6 |       TABLE ACCESS FULL          | CS_TARGET_MODEL_REL    |     1 |    26 |    84   (2)| 00:00:02 |
    |*  7 |       TABLE ACCESS BY INDEX ROWID| CS_AREA                |     1 |    26 |     1   (0)| 00:00:01 |
    |*  8 |        INDEX UNIQUE SCAN         | PK_CS_AREA_NEW         |     1 |       |     0   (0)| 00:00:01 |
    |*  9 |      INDEX RANGE SCAN            | IDX_CS_PFC_CURRENT     |     1 |       |     1   (0)| 00:00:01 |
    -----------------------------------------------------------------------------------------------------------
     
    Predicate Information (identified by operation id):
    ---------------------------------------------------
     
       6 - filter("D"."STAFF_ID"=8 AND "D"."ASSESS_ID"=1265 AND "D"."TARGET_MODEL_ID"=332 AND 
                  "D"."STATE"='2')
       7 - filter("M"."AREA_NAME"='永兴支局')
       8 - access("D"."AREA_ID"="M"."AREA_ID")
       9 - access("A"."TARGET_MODE_SEQ_ID"="D"."SEQ_ID")
    
    已用时间:  00: 00: 00.18
    
    统计信息
    ----------------------------------------------------------
              0  recursive calls
              0  db block gets
            386  consistent gets
              0  physical reads
              0  redo size
            544  bytes sent via SQL*Net to client
            998  bytes received via SQL*Net from client
              3  SQL*Net roundtrips to/from client
              1  sorts (memory)
              0  sorts (disk)
              0  rows processed


    现在逻辑读降低到386

    在Oracle当中,强烈建议 =使用 merge 代替 update语句


     

  • 相关阅读:
    MySQL锁机制和主从复制
    MySQL索引优化
    MySQL的Explain
    事务并发问题和隔离级别
    解决angular单页面页面底部跳转到新页面滚动条不在顶部的问题
    关于字符串在ie浏览器拼接问题
    angular 新建命令
    angular 多路由模块新建组件的方法
    Angular 4.x NgClass ngStyle 指令用法
    slideDown()、slideUp()反复执行的问题
  • 原文地址:https://www.cnblogs.com/hehe520/p/6330556.html
Copyright © 2011-2022 走看看