是的,Oracle 将重写查询以将 table1 连接到使用视图查询。因此,如果t1.column2 = somevalue AND t1.column3 = someothervalue
是选择性的并且 Oracle 意识到了这一点,您应该在计划中看到查询将从 TABLE1 驱动,然后连接到使用视图中的表中。只需运行一个解释计划来检查它。IE
set linesize 200 pagesize 200
explain plan for
merge....;
select * from table(dbms_xplan.display());
您应该会看到 Oracle 已经为您完成了这项工作。
例如:
SQL> create table table1(id number primary key, t2_id number, str varchar2(20), notes varchar2(20));
Table created.
SQL> create table table2(id number primary key, notes varchar2(20));
Table created.
SQL>
SQL> insert into table1
2 select rownum, rownum, case mod(rownum, 100) when 0 then 'ONE' else 'TWO' end, null
3 from dual connect by level <=1000000;
1000000 rows created.
SQL>
SQL> insert into table2
2 select rownum, dbms_random.string('x', 10)
3 from dual connect by level <=1000000;
1000000 rows created.
SQL>
SQL> create index table1_idx on table1(str);
Index created.
SQL> exec dbms_stats.gather_table_stats(user, 'TABLE1', method_opt=>'for all indexed columns size skewonly');
PL/SQL procedure successfully completed.
SQL> exec dbms_stats.gather_table_stats(user, 'TABLE2');
PL/SQL procedure successfully completed.
所以生病添加t1.str = 'ONE'
时非常有选择性:
SQL> explain plan for
2 merge into table1 t1
3 using (select * from table2 t where t.id > 1000) t2
4 on (t2.id = t1.t2_id and t1.str = 'ONE')
5 when matched then update
6 set t1.notes = t2.notes;
Explained.
SQL> @explain ""
Plan hash value: 2050534005
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------
| 0 | MERGE STATEMENT | | 441 | 11025 | 929 (5)| 00:00:12 |
| 1 | MERGE | TABLE1 | | | | |
| 2 | VIEW | | | | | |
|* 3 | HASH JOIN | | 441 | 12348 | 929 (5)| 00:00:12 |
|* 4 | TABLE ACCESS BY INDEX ROWID| TABLE1 | 441 | 5733 | 69 (2)| 00:00:01 |
|* 5 | INDEX RANGE SCAN | TABLE1_IDX | 8828 | | 21 (0)| 00:00:01 |
|* 6 | TABLE ACCESS FULL | TABLE2 | 994K| 14M| 848 (4)| 00:00:11 |
-------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("T"."ID"="T1"."T2_ID")
4 - filter("T1"."T2_ID">1000)
5 - access("T1"."STR"='ONE')
6 - filter("T"."ID">1000)
您可以看到它在 table1 上应用了索引
INDEX RANGE SCAN | TABLE1_IDX
因此删除了在 table1 上扫描的大量行(考虑到我的表,哈希连接更合适,但在您的情况下,您可能会在连接步骤中看到嵌套循环方法)。