Oracle Merge into中修改表的限制条件位置的区别

Oracle Merge into中修改表的限制条件位置的区别

前言

版本:11.2.0.4.0

说明:不讨论有insert子句的情况

对于样例语句如下:

merge into t1
using t2
on (t1.id = t2.id)
when matched then
  update set t1.name = t2.name;

想对t1做限制只更新t1.id=1的语句,那么下边3条SQL有什么区别:

merge into (select * from t1 where t1.id=1) tt1  |  merge into t1                                  |  merge into t1
using t2                                         |  using t2                                       |  using t2
on (tt1.id = t2.id)                              |  on (t1.id = t2.id)                             |  on (t1.id = t2.id and t1.id=1)
when matched then                                |  when matched then                              |  when matched then
  update set t1.name = t2.name;                  |    update set t1.name = t2.name where t1.id=1;  |    update set t1.name = t2.name;

构造环境

按照https://www.cnblogs.com/wangrui1587165/p/9844979.html里边的表做案例吧。

create table student (stu_id varchar2(4),stu_name varchar2(4),sex varchar2(1),credit varchar2(2));
insert into student values('0001','大王','2','88');
insert into student values('0002','刘一','1','88');
insert into student values('0003','陈二','2','66');
insert into student values('0004','张三','0','66');


create table student_temp (stu_id varchar2(4),stu_name varchar2(4),sex varchar2(1),credit varchar2(2));
insert into student_temp values('0001','大王','2','77');
insert into student_temp values('0002','刘一','1','77');
commit;

表数据如下:

17:04:52 ZKM@zkm(413)> select * from student;

STU_ID       STU_NAME     SEX CREDIT
------------ ------------ --- ------
0001         大王         2   88
0002         刘一         1   88
0003         陈二         2   66
0004         张三         0   66

Elapsed: 00:00:00.00
17:04:56 ZKM@zkm(413)> select * from student_temp;

STU_ID       STU_NAME     SEX CREDIT
------------ ------------ --- ------
0001         大王         2   77
0002         刘一         1   77

Elapsed: 00:00:00.00

对如下三条语句做比对:

1                                                                   2                                                               3
merge into (select * from student_temp where stu_id = '0001') t1 | merge into student_temp t1 | merge into student_temp t1 using (select stu_id, stu_name, sex, credit from student) t2 | using (select stu_id, stu_name, sex, credit from student) t2 | using (select stu_id, stu_name, sex, credit from student) t2 on (t1.stu_id = t2.stu_id) | on (t1.stu_id = t2.stu_id) | on (t1.stu_id = t2.stu_id and t1.stu_id = '0001') when matched then | when matched then | when matched then update set t1.credit = t2.credit ; | update set t1.credit = t2.credit where t1.stu_id = '0001'; | update set t1.credit = t2.credit;

执行计划和执行后表student_temp数据结果如下:

1.

16:01:46 ZKM@zkm(392)> select * from student_temp;

STU_ID       STU_NAME     SEX CREDIT
------------ ------------ --- ------
0001         大王         2   88
0002         刘一         1   77

-------------------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem | -------------------------------------------------------------------------------------------------------------------------- | 0 | MERGE STATEMENT | | 1 | | 0 |00:00:00.01 | 16 | | | | | 1 | MERGE | STUDENT_TEMP | 1 | | 0 |00:00:00.01 | 16 | | | | | 2 | VIEW | | 1 | | 1 |00:00:00.01 | 14 | | | | |* 3 | HASH JOIN | | 1 | 1 | 1 |00:00:00.01 | 14 | 1421K| 1421K| 695K (0)| |* 4 | TABLE ACCESS FULL| STUDENT | 1 | 1 | 1 |00:00:00.01 | 7 | | | | |* 5 | TABLE ACCESS FULL| STUDENT_TEMP | 1 | 1 | 1 |00:00:00.01 | 7 | | | | -------------------------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("STUDENT_TEMP"."STU_ID"="STU_ID") 4 - filter("STU_ID"='0001') 5 - filter("STU_ID"='0001')

2.

16:02:24 ZKM@zkm(392)> select * from student_temp;

STU_ID       STU_NAME     SEX CREDIT
------------ ------------ --- ------
0001         大王         2   88
0002         刘一         1   77
--------------------------------------------------------------------------------------------------------------------------
| Id  | Operation            | Name         | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
--------------------------------------------------------------------------------------------------------------------------
|   0 | MERGE STATEMENT      |              |      1 |        |      0 |00:00:00.01 |      16 |       |       |          |
|   1 |  MERGE               | STUDENT_TEMP |      1 |        |      0 |00:00:00.01 |      16 |       |       |          |
|   2 |   VIEW               |              |      1 |        |      2 |00:00:00.01 |      14 |       |       |          |
|*  3 |    HASH JOIN         |              |      1 |      2 |      2 |00:00:00.01 |      14 |  1185K|  1185K|  795K (0)|
|   4 |     TABLE ACCESS FULL| STUDENT_TEMP |      1 |      2 |      2 |00:00:00.01 |       7 |       |       |          |
|   5 |     TABLE ACCESS FULL| STUDENT      |      1 |      4 |      4 |00:00:00.01 |       7 |       |       |          |
--------------------------------------------------------------------------------------------------------------------------

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

   3 - access("T1"."STU_ID"="STU_ID")

3.

16:03:05 ZKM@zkm(392)> select * from student_temp;

STU_ID       STU_NAME     SEX CREDIT
------------ ------------ --- ------
0001         大王         2   88
0002         刘一         1   77
--------------------------------------------------------------------------------------------------------------------------
| Id  | Operation            | Name         | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
--------------------------------------------------------------------------------------------------------------------------
|   0 | MERGE STATEMENT      |              |      1 |        |      0 |00:00:00.01 |      16 |       |       |          |
|   1 |  MERGE               | STUDENT_TEMP |      1 |        |      0 |00:00:00.01 |      16 |       |       |          |
|   2 |   VIEW               |              |      1 |        |      1 |00:00:00.01 |      14 |       |       |          |
|*  3 |    HASH JOIN         |              |      1 |      1 |      1 |00:00:00.01 |      14 |  1421K|  1421K|  695K (0)|
|*  4 |     TABLE ACCESS FULL| STUDENT      |      1 |      1 |      1 |00:00:00.01 |       7 |       |       |          |
|*  5 |     TABLE ACCESS FULL| STUDENT_TEMP |      1 |      1 |      1 |00:00:00.01 |       7 |       |       |          |
--------------------------------------------------------------------------------------------------------------------------

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

   3 - access("T1"."STU_ID"="STU_ID")
   4 - filter("STU_ID"='0001')
   5 - filter("T1"."STU_ID"='0001')

对于结果,可以得到:

1                                                                   2                                                               3
merge into (select * from student_temp where stu_id = '0001') t1 |  merge into student_temp t1                                    | merge into student_temp t1
using (select stu_id, stu_name, sex, credit from student) t2     |  using (select stu_id, stu_name, sex, credit from student) t2  | using (select stu_id, stu_name, sex, credit from student) t2
on (t1.stu_id = t2.stu_id)                                       |  on (t1.stu_id = t2.stu_id)                                    | on (t1.stu_id = t2.stu_id and t1.stu_id = '0001')
when matched then                                                |  when matched then                                             | when matched then
  update set t1.credit = t2.credit ;                             |    update set t1.credit = t2.credit where t1.stu_id = '0001';  |   update set t1.credit = t2.credit;

执行结果均相同,若是HASH JOIN前提下,对于第2条语句消耗的内存更多,这是因为第2条在id4和id5处没有对student和student_temp表先做过滤。而第1条和第3条则一样的性能

建议使用第1种写法。原因是第3种写法从理解上看没有第一种好理解。

而且如果在when not matched when insert子句下,意义就完全不一样了,参考https://www.cnblogs.com/wangrui1587165/p/9844979.html

参考

https://www.cnblogs.com/wangrui1587165/p/9844979.html

ORACLE sql merge into update where条件位置与性能消耗

原文地址:https://www.cnblogs.com/PiscesCanon/p/14422368.html