用Merge改写优化Update

1. 多列关联更新改写示例

1. 模拟数据
create table t_objects as select * from dba_objects;
create table t_tables as select * from dba_tables;
alter table t_objects add tablespace_name varchar2(30);
alter table t_objects add flag varchar2(2);

2. 现在需要把t_tables.object_id>10000的t_tables.tablespace_name与t_tables.'2'的值
更新到t_objects.tablespace_name 与t_objects.flag。

错误的写法:
update t_objects a
   set (a.tablespace_name, a.flag) =
       (select b.tablespace_name, '2'
          from t_tables b
         where a.owner = b.owner
           and a.object_name = b.table_name)
 where  a.object_id> 10000

因为如果where子句不加
(exists (select b.tablespace_name from t_tables b 
where a.owner = b.owner and a.object_name = b.table_name))
的话,会多处理一些没有关联上的数据,而这些没关联上的数据,是用null值更新的。

正确的写法:
update t_objects a
   set (a.tablespace_name, a.flag) =
       (select b.tablespace_name, '2'
          from t_tables b
         where a.owner = b.owner
           and a.object_name = b.table_name)
 where exists (select b.tablespace_name
          from t_tables b
         where a.owner = b.owner
           and a.object_name = b.table_name)
      and a.object_id> 10000

Elapsed: 00:00:00.67

Execution Plan
----------------------------------------------------------
Plan hash value: 2130220419

-----------------------------------------------------------------------------------
| Id  | Operation             | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------
|   0 | UPDATE STATEMENT      |           | 23341 |  3419K|  1027K  (5)| 03:25:26 |
|   1 |  UPDATE               | T_OBJECTS |       |       |            |          |
|*  2 |   HASH JOIN RIGHT SEMI|           | 23341 |  3419K|    93   (3)| 00:00:02 |
|   3 |    VIEW               | VW_SQ_1   |  3062 |   101K|    21   (0)| 00:00:01 |
|   4 |     TABLE ACCESS FULL | T_TABLES  |  3062 |   101K|    21   (0)| 00:00:01 |
|*  5 |    TABLE ACCESS FULL  | T_OBJECTS | 23346 |  2644K|    71   (2)| 00:00:01 |
|*  6 |   TABLE ACCESS FULL   | T_TABLES  |     1 |    51 |    21   (0)| 00:00:01 |
-----------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("A"."OWNER"="ITEM_1" AND "A"."OBJECT_NAME"="ITEM_2")
   5 - filter("A"."OBJECT_ID">10000)
   6 - filter("B"."OWNER"=:B1 AND "B"."TABLE_NAME"=:B2)

Note
-----
   - dynamic sampling used for this statement (level=2)


Statistics
----------------------------------------------------------
          0  recursive calls
       2614  db block gets
     255891  consistent gets
        507  physical reads
     643016  redo size
        839  bytes sent via SQL*Net to client
       1115  bytes received via SQL*Net from client
          3  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
       2555  rows processed


3. 利用merge改写后

merge into t_objects a
using t_tables b
on (a.owner = b.owner and a.object_name = b.table_name)
when matched then
  update set a.tablespace_name = b.tablespace_name, a.flag = '2'
where a.object_id> 10000

Elapsed: 00:00:00.06

Execution Plan
----------------------------------------------------------
Plan hash value: 1970127410

------------------------------------------------------------------------------------------
| Id  | Operation            | Name      | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------
|   0 | MERGE STATEMENT      |           |  3062 |   768K|       |   567   (1)| 00:00:07 |
|   1 |  MERGE               | T_OBJECTS |       |       |       |            |          |
|   2 |   VIEW               |           |       |       |       |            |          |
|*  3 |    HASH JOIN         |           |  3062 |  2332K|  1656K|   567   (1)| 00:00:07 |
|   4 |     TABLE ACCESS FULL| T_TABLES  |  3062 |  1617K|       |    21   (0)| 00:00:01 |
|   5 |     TABLE ACCESS FULL| T_OBJECTS | 33077 |  7720K|       |    71   (2)| 00:00:01 |
------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access("A"."OWNER"="B"."OWNER" AND "A"."OBJECT_NAME"="B"."TABLE_NAME")

Note
-----
   - dynamic sampling used for this statement (level=2)


Statistics
----------------------------------------------------------
          0  recursive calls
       2605  db block gets
        511  consistent gets
          0  physical reads
     607260  redo size
        840  bytes sent via SQL*Net to client
        955  bytes received via SQL*Net from client
          3  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
       2555  rows processed
      
4. 优化后的物理读与逻辑读,都比之前减少很多,执行时间也少了许多。      

2. 用Merge改写有聚合操作的Update

1. 模拟数据
create table t_objects as select * from dba_objects;
create table t_tables as select * from dba_tables;

insert into t_tables  select * from t_tables;
insert into t_tables  select * from t_tables;
insert into t_tables  select * from t_tables;
commit;

alter table t_objects add tablespace_name varchar2(30);
alter table t_objects add flag varchar2(2);


2. 更新数据到t_objects表中
update t_objects a
   set (a.tablespace_name, a.flag) =
       (select distinct b.tablespace_name, '2'
          from t_tables b
         where a.owner = b.owner
           and a.object_name = b.table_name)
 where exists (select distinct b.tablespace_name
          from t_tables b
         where a.owner = b.owner
           and a.object_name = b.table_name)
      and a.object_id> 10000

Elapsed: 00:00:04.84

Execution Plan
----------------------------------------------------------
Plan hash value: 1460256570

-----------------------------------------------------------------------------------
| Id  | Operation             | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------
|   0 | UPDATE STATEMENT      |           | 23346 |  3419K|  7190K  (2)| 23:58:10 |
|   1 |  UPDATE               | T_OBJECTS |       |       |            |          |
|*  2 |   HASH JOIN RIGHT SEMI|           | 23346 |  3419K|   225   (2)| 00:00:03 |
|   3 |    VIEW               | VW_SQ_1   | 26203 |   870K|   153   (1)| 00:00:02 |
|   4 |     TABLE ACCESS FULL | T_TABLES  | 26203 |   870K|   153   (1)| 00:00:02 |
|*  5 |    TABLE ACCESS FULL  | T_OBJECTS | 23346 |  2644K|    71   (2)| 00:00:01 |
|   6 |   HASH UNIQUE         |           |     3 |   153 |   154   (2)| 00:00:02 |
|*  7 |    TABLE ACCESS FULL  | T_TABLES  |     3 |   153 |   153   (1)| 00:00:02 |
-----------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("A"."OWNER"="ITEM_1" AND "A"."OBJECT_NAME"="ITEM_2")
   5 - filter("A"."OBJECT_ID">10000)
   7 - filter("B"."OWNER"=:B1 AND "B"."TABLE_NAME"=:B2)

Note
-----
   - dynamic sampling used for this statement (level=2)


Statistics
----------------------------------------------------------
         28  recursive calls
       5202  db block gets
    1972653  consistent gets
          0  physical reads
    1119588  redo size
        824  bytes sent via SQL*Net to client
       1144  bytes received via SQL*Net from client
          3  SQL*Net roundtrips to/from client
          3  sorts (memory)
          0  sorts (disk)
       2555  rows processed

3. merge改写
 merge into (select owner, object_name, tablespace_name, flag
               from t_objects
              where object_id > 10000) a
 using (select owner, table_name, tablespace_name
          from t_tables
         group by owner, table_name, tablespace_name) b
 on (a.owner = b.owner and a.object_name = b.table_name)
 when matched then
   update set a.tablespace_name = b.tablespace_name, a.flag = '2'

Elapsed: 00:00:00.07

Execution Plan
----------------------------------------------------------
Plan hash value: 1597301946

-------------------------------------------------------------------------------------------
| Id  | Operation             | Name      | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------
|   0 | MERGE STATEMENT       |           | 23346 |  1139K|       |   460   (2)| 00:00:06 |
|   1 |  MERGE                | T_OBJECTS |       |       |       |            |          |
|   2 |   VIEW                |           |       |       |       |            |          |
|   3 |    SORT GROUP BY      |           | 23346 |  4080K|       |   460   (2)| 00:00:06 |
|*  4 |     HASH JOIN         |           | 23346 |  4080K|  1616K|   458   (1)| 00:00:06 |
|   5 |      TABLE ACCESS FULL| T_TABLES  | 26203 |  1305K|       |   153   (1)| 00:00:02 |
|*  6 |      TABLE ACCESS FULL| T_OBJECTS | 23346 |  2918K|       |    71   (2)| 00:00:01 |
-------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   4 - access("OWNER"="OWNER" AND "OBJECT_NAME"="TABLE_NAME")
   6 - filter("OBJECT_ID">10000)

Note
-----
   - dynamic sampling used for this statement (level=2)


Statistics
----------------------------------------------------------
          9  recursive calls
       2623  db block gets
       1274  consistent gets
          0  physical reads
     643324  redo size
        840  bytes sent via SQL*Net to client
       1161  bytes received via SQL*Net from client
          3  SQL*Net roundtrips to/from client
          2  sorts (memory)
          0  sorts (disk)
       2555  rows processed  
       
4. merge 改写后,性能大大提升 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值