利用Merge代替复杂的UPDATE语句

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

[html]  view plain copy print ?
  1. UPDATE CS_PERFORMANCE_CURRENT C  
  2.    SET C.PERFORMANCE_SCORE = '0.00'C.ASSESS_DESC = '劳动纪律考核'  
  3.  WHERE C.TARGET_MODE_SEQ_ID =  
  4.        (SELECT D.SEQ_ID  
  5.           FROM CS_TARGET_MODEL_REL D, CS_AREA A  
  6.          WHERE D.ASSESS_ID = 1265  
  7.            AND C.TARGET_MODE_SEQ_ID = D.SEQ_ID  
  8.            AND D.STAFF_ID = 8  
  9.            AND C.COM_DATE = TO_DATE('20110801','YYYYMMDD')  
  10.            AND D.TARGET_MODEL_ID = 332  
  11.            AND D.STATE = TO_CHAR(2)  
  12.            AND D.AREA_ID = A.AREA_ID  
  13.            AND A.AREA_NAME = '永兴支局');  
  14.   
  15. Plan hash value: 2321634139  
  16.    
  17. ----------------------------------------------------------------------------------------------------------  
  18. | Id  | Operation                       | Name                   | Rows  | Bytes | Cost (%CPU)| Time     |  
  19. ----------------------------------------------------------------------------------------------------------  
  20. |   0 | UPDATE STATEMENT                |                        |     1 |    41 |   679   (1)| 00:00:09 |  
  21. |   1 |  UPDATE                         | CS_PERFORMANCE_CURRENT |       |       |            |          |  
  22. |*  2 |   FILTER                        |                        |       |       |            |          |  
  23. |   3 |    TABLE ACCESS FULL            | CS_PERFORMANCE_CURRENT |   124K|  4968K|   664   (1)| 00:00:08 |  
  24. |*  4 |    FILTER                       |                        |       |       |            |          |  
  25. |   5 |     NESTED LOOPS                |                        |     1 |    52 |     3   (0)| 00:00:01 |  
  26. |*  6 |      TABLE ACCESS BY INDEX ROWID| CS_TARGET_MODEL_REL    |     1 |    26 |     2   (0)| 00:00:01 |  
  27. |*  7 |       INDEX UNIQUE SCAN         | PK_CS_TARGET_RULE_REL  |     1 |       |     1   (0)| 00:00:01 |  
  28. |*  8 |      TABLE ACCESS BY INDEX ROWID| CS_AREA                |     1 |    26 |     1   (0)| 00:00:01 |  
  29. |*  9 |       INDEX UNIQUE SCAN         | PK_CS_AREA_NEW         |     1 |       |     0   (0)| 00:00:01 |  
  30. ----------------------------------------------------------------------------------------------------------  
  31.    
  32. Predicate Information (identified by operation id):  
  33. ---------------------------------------------------  
  34.    
  35.    2 - filter("C"."TARGET_MODE_SEQ_ID"= (SELECT "D"."SEQ_ID" FROM "CS_AREA"   
  36.               "A","CS_TARGET_MODEL_REL" "D" WHERE :B1=TO_DATE(' 2011-08-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss')   
  37.               AND "D"."SEQ_ID"=:B2 AND "D"."STAFF_ID"=8 AND "D"."ASSESS_ID"=1265 AND "D"."TARGET_MODEL_ID"=332   
  38.               AND "D"."STATE"='2' AND "D"."AREA_ID"="A"."AREA_ID" AND "A"."AREA_NAME"='永兴支局'))  
  39.    4 - filter(:B1=TO_DATE(' 2011-08-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss'))  
  40.    6 - filter("D"."STAFF_ID"=8 AND "D"."ASSESS_ID"=1265 AND "D"."TARGET_MODEL_ID"=332 AND   
  41.               "D"."STATE"='2')  
  42.    7 - access("D"."SEQ_ID"=:B1)  
  43.    8 - filter("A"."AREA_NAME"='永兴支局')  
  44.    9 - access("D"."AREA_ID"="A"."AREA_ID")  
  45.   
  46. 已用时间:  00: 00: 00.29  
  47.   
  48. 统计信息  
  49. ----------------------------------------------------------  
  50.           1  recursive calls  
  51.           0  db block gets  
  52.       32670  consistent gets  
  53.          21  physical reads  
  54.           0  redo size  
  55.         536  bytes sent via SQL*Net to client  
  56.         978  bytes received via SQL*Net from client  
  57.           3  SQL*Net roundtrips to/from client  
  58.           1  sorts (memory)  
  59.           0  sorts (disk)  
  60.           0  rows processed  
[html]  view plain copy print ?
  1. UPDATE /*+ PUSH_SUBQ(@D) */CS_PERFORMANCE_CURRENT C  
  2.    SET C.PERFORMANCE_SCORE = '0.00'C.ASSESS_DESC = '劳动纪律考核'  
  3.  WHERE C.TARGET_MODE_SEQ_ID =  
  4.        (SELECT /*+ QB_NAME(D) */ D.SEQ_ID  
  5.           FROM CS_TARGET_MODEL_REL D, CS_AREA A  
  6.          WHERE D.ASSESS_ID = 1265  
  7.            AND C.TARGET_MODE_SEQ_ID = D.SEQ_ID  
  8.            AND D.STAFF_ID = 8  
  9.            AND C.COM_DATE = TO_DATE('20110801','YYYYMMDD')  
  10.            AND D.TARGET_MODEL_ID = 332  
  11.            AND D.STATE = TO_CHAR(2)  
  12.            AND D.AREA_ID = A.AREA_ID  
  13.            AND A.AREA_NAME = '永兴支局')  
  14.              
  15. Plan hash value: 4189652906  
  16.    
  17. ----------------------------------------------------------------------------------------------------------  
  18. | Id  | Operation                       | Name                   | Rows  | Bytes | Cost (%CPU)| Time     |  
  19. ----------------------------------------------------------------------------------------------------------  
  20. |   0 | UPDATE STATEMENT                |                        |     1 |    39 |    43   (0)| 00:00:01 |  
  21. |   1 |  UPDATE                         | CS_PERFORMANCE_CURRENT |       |       |            |          |  
  22. |*  2 |   TABLE ACCESS FULL             | CS_PERFORMANCE_CURRENT |     1 |    39 |    40   (0)| 00:00:01 |  
  23. |*  3 |    FILTER                       |                        |       |       |            |          |  
  24. |   4 |     NESTED LOOPS                |                        |     1 |    47 |     3   (0)| 00:00:01 |  
  25. |*  5 |      TABLE ACCESS BY INDEX ROWID| CS_TARGET_MODEL_REL    |     1 |    25 |     2   (0)| 00:00:01 |  
  26. |*  6 |       INDEX UNIQUE SCAN         | PK_CS_TARGET_RULE_REL  |     1 |       |     1   (0)| 00:00:01 |  
  27. |*  7 |      TABLE ACCESS BY INDEX ROWID| CS_AREA                |     1 |    22 |     1   (0)| 00:00:01 |  
  28. |*  8 |       INDEX UNIQUE SCAN         | PK_CS_AREA_NEW         |     1 |       |     0   (0)| 00:00:01 |  
  29. ----------------------------------------------------------------------------------------------------------  
  30.    
  31. Predicate Information (identified by operation id):  
  32. ---------------------------------------------------  
  33.    
  34.    2 - filter("C"."TARGET_MODE_SEQ_ID"= (SELECT /*+ PUSH_SUBQ QB_NAME ("D") */ "D"."SEQ_ID" FROM   
  35.               "CS_AREA" "A","CS_TARGET_MODEL_REL" "D" WHERE :B1=TO_DATE(' 2011-08-01 00:00:00', 'syyyy-mm-dd   
  36.               hh24:mi:ss') AND "D"."SEQ_ID"=:B2 AND "D"."ASSESS_ID"=1265 AND "D"."STAFF_ID"=8 AND   
  37.               "D"."TARGET_MODEL_ID"=332 AND "D"."STATE"='2' AND "D"."AREA_ID"="A"."AREA_ID" AND   
  38.               "A"."AREA_NAME"='永兴支局'))  
  39.    3 - filter(:B1=TO_DATE(' 2011-08-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss'))  
  40.    5 - filter("D"."ASSESS_ID"=1265 AND "D"."STAFF_ID"=8 AND "D"."TARGET_MODEL_ID"=332 AND   
  41.               "D"."STATE"='2')  
  42.    6 - access("D"."SEQ_ID"=:B1)  
  43.    7 - filter("A"."AREA_NAME"='永兴支局')  
  44.    8 - access("D"."AREA_ID"="A"."AREA_ID")  
  45.   
  46. 统计信息  
  47. ----------------------------------------------------------  
  48.           1  recursive calls  
  49.           0  db block gets  
  50.       32670  consistent gets  
  51.          21  physical reads  
  52.           0  redo size  
  53.         536  bytes sent via SQL*Net to client  
  54.         978  bytes received via SQL*Net from client  
  55.           3  SQL*Net roundtrips to/from client  
  56.           1  sorts (memory)  
  57.           0  sorts (disk)  
  58.           0  rows processed  

 

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

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

[html]  view plain copy print ?
  1. MERGE INTO CS_PERFORMANCE_CURRENT A  
  2. USING (SELECT D.SEQ_ID  
  3.        FROM   CS_TARGET_MODEL_REL D,  
  4.               CS_AREA             M  
  5.        WHERE  D.ASSESS_ID = 1265 AND  
  6.               D.STAFF_ID = 8 AND  
  7.               D.TARGET_MODEL_ID = 332 AND  
  8.               D.STATE = TO_CHAR(2) AND  
  9.               D.AREA_ID = M.AREA_ID AND  
  10.               M.AREA_NAME = '永兴支局') H  
  11. ON (A.TARGET_MODE_SEQ_ID = H.SEQ_ID)  
  12. WHEN MATCHED THEN  
  13.   UPDATE SET A.PERFORMANCE_SCORE = '0.00'A.ASSESS_DESC = '劳动纪律考核' WHERE A.COM_DATE = TO_DATE('20110801', 'YYYYMMDD');  
  14.    
  15.  ----------------------------------------------------------------------------------------------------------  
  16.  | Id  | Operation                       | Name                   | Rows  | Bytes | Cost (%CPU)| Time     |  
  17.  ----------------------------------------------------------------------------------------------------------  
  18.  |   0 | MERGE STATEMENT                 |                        |     1 |   167 |   750   (1)| 00:00:10 |  
  19.  |   1 |  MERGE                          | CS_PERFORMANCE_CURRENT |       |       |            |          |  
  20.  |   2 |   VIEW                          |                        |       |       |            |          |  
  21.  |*  3 |    HASH JOIN                    |                        |     1 |   210 |   750   (1)| 00:00:10 |  
  22.  |   4 |     NESTED LOOPS                |                        |     1 |    52 |    85   (2)| 00:00:02 |  
  23.  |*  5 |      TABLE ACCESS FULL          | CS_TARGET_MODEL_REL    |     1 |    26 |    84   (2)| 00:00:02 |  
  24.  |*  6 |      TABLE ACCESS BY INDEX ROWID| CS_AREA                |     1 |    26 |     1   (0)| 00:00:01 |  
  25.  |*  7 |       INDEX UNIQUE SCAN         | PK_CS_AREA_NEW         |     1 |       |     0   (0)| 00:00:01 |  
  26.  |   8 |     TABLE ACCESS FULL           | CS_PERFORMANCE_CURRENT |   124K|    18M|   664   (1)| 00:00:08 |  
  27.  ----------------------------------------------------------------------------------------------------------  
  28.     
  29.  Predicate Information (identified by operation id):  
  30.  ---------------------------------------------------  
  31.     
  32.     3 - access("A"."TARGET_MODE_SEQ_ID"="D"."SEQ_ID")  
  33.     5 - filter("D"."STAFF_ID"=8 AND "D"."ASSESS_ID"=1265 AND "D"."TARGET_MODEL_ID"=332 AND   
  34.                "D"."STATE"='2')  
  35.     6 - filter("M"."AREA_NAME"='永兴支局')  
  36.     7 - access("D"."AREA_ID"="M"."AREA_ID")  
  37.             
  38.             
  39. 统计信息  
  40. ----------------------------------------------------------  
  41.         333  recursive calls  
  42.           0  db block gets  
  43.        3474  consistent gets  
  44.           3  physical reads  
  45.           0  redo size  
  46.         546  bytes sent via SQL*Net to client  
  47.         998  bytes received via SQL*Net from client  
  48.           3  SQL*Net roundtrips to/from client  
  49.          15  sorts (memory)  
  50.           0  sorts (disk)  
  51.           0  rows processed            


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

[html]  view plain copy print ?
  1. Plan hash value: 3908453434  
  2.    
  3. -----------------------------------------------------------------------------------------------------------  
  4. | Id  | Operation                        | Name                   | Rows  | Bytes | Cost (%CPU)| Time     |  
  5. -----------------------------------------------------------------------------------------------------------  
  6. |   0 | MERGE STATEMENT                  |                        |     1 |   167 |    88   (2)| 00:00:02 |  
  7. |   1 |  MERGE                           | CS_PERFORMANCE_CURRENT |       |       |            |          |  
  8. |   2 |   VIEW                           |                        |       |       |            |          |  
  9. |   3 |    TABLE ACCESS BY INDEX ROWID   | CS_PERFORMANCE_CURRENT |     1 |   158 |     3   (0)| 00:00:01 |  
  10. |   4 |     NESTED LOOPS                 |                        |     1 |   210 |    88   (2)| 00:00:02 |  
  11. |   5 |      NESTED LOOPS                |                        |     1 |    52 |    85   (2)| 00:00:02 |  
  12. |*  6 |       TABLE ACCESS FULL          | CS_TARGET_MODEL_REL    |     1 |    26 |    84   (2)| 00:00:02 |  
  13. |*  7 |       TABLE ACCESS BY INDEX ROWID| CS_AREA                |     1 |    26 |     1   (0)| 00:00:01 |  
  14. |*  8 |        INDEX UNIQUE SCAN         | PK_CS_AREA_NEW         |     1 |       |     0   (0)| 00:00:01 |  
  15. |*  9 |      INDEX RANGE SCAN            | IDX_CS_PFC_CURRENT     |     1 |       |     1   (0)| 00:00:01 |  
  16. -----------------------------------------------------------------------------------------------------------  
  17.    
  18. Predicate Information (identified by operation id):  
  19. ---------------------------------------------------  
  20.    
  21.    6 - filter("D"."STAFF_ID"=8 AND "D"."ASSESS_ID"=1265 AND "D"."TARGET_MODEL_ID"=332 AND   
  22.               "D"."STATE"='2')  
  23.    7 - filter("M"."AREA_NAME"='永兴支局')  
  24.    8 - access("D"."AREA_ID"="M"."AREA_ID")  
  25.    9 - access("A"."TARGET_MODE_SEQ_ID"="D"."SEQ_ID")  
  26.   
  27. 已用时间:  00: 00: 00.18  
  28.   
  29. 统计信息  
  30. ----------------------------------------------------------  
  31.           0  recursive calls  
  32.           0  db block gets  
  33.         386  consistent gets  
  34.           0  physical reads  
  35.           0  redo size  
  36.         544  bytes sent via SQL*Net to client  
  37.         998  bytes received via SQL*Net from client  
  38.           3  SQL*Net roundtrips to/from client  
  39.           1  sorts (memory)  
  40.           0  sorts (disk)  
  41.           0  rows processed  


现在逻辑读降低到386

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


转载:http://blog.csdn.net/robinson1988/article/details/7042543#comments

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值