MK0*_*K01 5 oracle join optimization
我有一个查询,看起来像
SELECT *
FROM table0
WHERE id IN (SELECT id FROM table1 JOIN table2)
Run Code Online (Sandbox Code Playgroud)
Oracle 选择使用嵌套循环将 table0 与 (table1 x table2) 的结果连接起来,这需要几个小时。我试图弄清楚我是否可以暗示它使用 HASH 来代替,但不知道使用哪个提示以及在哪里使用。我尝试将 HASH_SJ 和 HASH_AJ 贴在各个地方,但没有帮助...
小智 6
我会尝试将WITH
子句与MATERIALIZE
提示结合使用,以首先强制实现子查询。像这样的东西:
WITH x as (select /*+ MATERIALIZE */
from [your subquery join])
SELECT *
FROM table0, x
WHERE table0.id =x.id
Run Code Online (Sandbox Code Playgroud)
您可以在子查询中使用提示,例如,在使用提示限定它们之后QB_NAME
。
然而,在这种情况下,一个简单的USE_HASH
提示应该没问题。这是我的设置:
create table t0 (id integer primary key, pad char(500));
insert into t0 select rownum, 'x' from dual connect by level <= 2000;
create table t1 (t1_id integer primary key, id integer references t0, pad char(500));
insert into t1 select rownum, round(rownum/2), 'x' from dual connect by level <= 100;
create index i0 on t1(id);
create table t2 (t2_id integer primary key, t1_id integer references t1, pad char(500));
insert into t2 select rownum, round(rownum/2), 'x' from dual connect by level <= 100;
create index i1 on t2(t1_id);
exec dbms_stats.gather_table_stats(user, 'T0', cascade=>true);
exec dbms_stats.gather_table_stats(user, 'T1', cascade=>true);
exec dbms_stats.gather_table_stats(user, 'T2', cascade=>true);
Run Code Online (Sandbox Code Playgroud)
通过此设置,以下查询将运行 NESTED LOOP 连接:
SQL> EXPLAIN PLAN FOR
2 SELECT * FROM t0
3 WHERE id IN (SELECT id
4 FROM t1 JOIN t2 ON t1.t1_id = t2.t1_id
5 WHERE t2.pad LIKE :x);
Explained.
SQL> SELECT * FROM TABLE(DBMS_XPLAN.display);
-------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
-------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5 | 2585 | 37 |
| 1 | NESTED LOOPS | | 5 | 2585 | 37 |
| 2 | VIEW | VW_NSO_1 | 5 | 65 | 7 |
| 3 | SORT UNIQUE | | 5 | 2550 | |
| 4 | HASH JOIN | | 5 | 2550 | 7 |
| 5 | TABLE ACCESS FULL | T1 | 100 | 600 | 3 |
| 6 | TABLE ACCESS FULL | T2 | 5 | 2520 | 3 |
| 7 | TABLE ACCESS BY INDEX ROWID| T0 | 1 | 504 | 1 |
| 8 | INDEX UNIQUE SCAN | SYS_C00746321 | 1 | | |
-------------------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)
随着USE_HASH
提示:
SQL> EXPLAIN PLAN FOR
2 SELECT /*+ USE_HASH (t0) */ * FROM t0
3 WHERE id IN (SELECT id
4 FROM t1 JOIN t2 ON t1.t1_id = t2.t1_id
5 WHERE t2.pad LIKE :x);
Explained.
SQL> SELECT * FROM TABLE(DBMS_XPLAN.display);
--------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
--------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5 | 2585 | 44 |
| 1 | HASH JOIN SEMI | | 5 | 2585 | 44 |
| 2 | TABLE ACCESS FULL | T0 | 2000 | 984K| 23 |
| 3 | VIEW | VW_NSO_1 | 5 | 65 | 7 |
| 4 | HASH JOIN | | 5 | 2550 | 7 |
| 5 | TABLE ACCESS FULL| T1 | 100 | 600 | 3 |
| 6 | TABLE ACCESS FULL| T2 | 5 | 2520 | 3 |
--------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)