๐ ์๋ชฉ์ฐจ
1. nested loop ์กฐ์ธ
2. hash ์กฐ์ธ
3. sort merge ์กฐ์ธ
4. ์กฐ์ธ ์์์ ์ค์์ฑ
5. outer ์กฐ์ธ
6. ์ค์นผ๋ผ ์๋ธ์ฟผ๋ฆฌ๋ฅผ ์ด์ฉํ ์กฐ์ธ ํ๋
7. ์กฐ์ธ์ ๋ดํฌํ DML ๋ฌธ ํ๋
8. ๊ณ ๊ธ ์กฐ์ธ ํ ํฌ๋
โ๏ธ ํ๋ ์
select /*+ gather_plan_statistics*/ ename, sal, (select sum(sal) from emp e2 where e2.empno <= e1.empno) sumsal from emp e1 order by empno; SELECT * FROM TABLE(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST')); ---------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem | ---------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 14 |00:00:00.01 | 105 | | | | | 1 | SORT AGGREGATE | | 14 | 1 | 14 |00:00:00.01 | 98 | | | | |* 2 | TABLE ACCESS FULL| EMP | 14 | 1 | 105 |00:00:00.01 | 98 | | | | | 3 | SORT ORDER BY | | 1 | 14 | 14 |00:00:00.01 | 105 | 2048 | 2048 | 2048 (0)| | 4 | TABLE ACCESS FULL| EMP | 1 | 14 | 14 |00:00:00.01 | 7 | | | | ----------------------------------------------------------------------------------------------------------------
โ๏ธ ํ๋ ํ
select /*+ gather_plan_statistics*/ ename, sal, sum(sal) over(order by empno) sumsal from emp; SELECT * FROM TABLE(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST')); ---------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem | ---------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 14 |00:00:00.01 | 7 | | | | | 1 | WINDOW SORT | | 1 | 14 | 14 |00:00:00.01 | 7 | 2048 | 2048 | 2048 (0)| | 2 | TABLE ACCESS FULL| EMP | 1 | 14 | 14 |00:00:00.01 | 7 | | | | ----------------------------------------------------------------------------------------------------------------
โ๏ธ ํ๋ ์ (๋ฒํผ ๊ฐฏ์ 105๊ฐ)
select /*+ gather_plan_statistics*/ deptno, ename, sal, (select sum(sal) from emp e2 where e2.empno <= e1.empno and e2.deptno=e1.deptno)sumsal from emp e1 order by deptno, emptno;
โก๏ธ ๊ฐ์ ๋ถ์๋ฒํธ๋ผ๋ฆฌ ๋์ ๋ ๊ฐ์ด ๋์ค๊ณ ์๋ค.
โ๏ธ ํ๋ ํ (๋ฒํผ ๊ฐฏ์ 7๊ฐ)select /*+ gather_plan_statistics*/ deptno, ename, sal, sum(sal) over(partition by deptno order by empno) sumsal from emp;
โ๏ธ ํ๋ ์
select /*+ gather_plan_statistics*/ decode(no,1, deptno, 2, null) as deptno, sum(sal) from emp e, (select rownum no from dual connect by level <= 2 ) d group by decode(no, 1, deptno, 2, null ) order by deptno;
โ๏ธ ํ๋ ํselect /*+ gather_plan_statistics*/ deptno, sum(sal) from emp group by rollup(deptno);
โ๏ธ ํ๋ ์
select decode(no,1, to_char(deptno), 2, 'ํ ํ') as deptno, sum(sal) from emp e, (select rownum no from dual connect by level <= 2 ) d group by decode(no, 1, to_char(deptno), 2, 'ํ ํ' ) order by deptno;โ๏ธ ํ๋ ํ
select /*+ gather_plan_statistics*/ nvl(to_char(deptno),'total'), deptno, sum(sal) from emp group by rollup(deptno);
โ๐ป ํ๊ฒฝ๊ตฌ์ฑ
@demo
alter table emp
add emp_kind varchar2(1) default 1 not null;
update emp
set emp_kind = case when mod(empno,2) = 1 then 1
else 2 end ;
select ename, emp_kind from emp;
-- emp_kind ๊ฐ 1์ด๋ฉด ์ ๊ท์ง
-- emp_kind ๊ฐ 2์ด๋ฉด ๋น์ ๊ท์ง

โ๏ธ ์ ๊ท์ง ์ฌ์ ํ ์ด๋ธ ์์ฑ
create table emp_kind1 as select empno, ename, sal + 200 as office_sal from emp where emp_kind ='1';โ๏ธ ๋น์ ๊ท์ง ์ฌ์ ํ ์ด๋ธ ์์ฑ
create table emp_kind2 as select empno, ename, sal + 200 as sal from emp where emp_kind ='2';โ๏ธ primary key ์ ์ฝ์ ๊ฐ๊ฐ ๊ฑด๋ค
alter table emp_kind1 add constraint pk_emp_kind1 primary key(empno); alter table emp_kind2 add constraint pk_emp_kind2 primary key(empno); -- ์๊ธ ์ปฌ๋ผ ๋ ๋ฆฌ๊ธฐ alter table emp drop column sal ; select * from emp_kind1; select * from emp_kind2;
โ ์๋์ SQL์ ํ๋ํ๊ธฐ
-- emp_kind1(์ ๊ท์ง์ฌ์) , emp_kind2(๋น์ ๊ท์ง์ฌ์), emp(๊ทธ๋ฅ์ฌ์)
select /*+ gather_plan_statistics*/ e.empno, e.ename, k1.office_sal, k2.sal
from emp e, emp_kind1 k1, emp_kind2 k2
where e.empno = k1.empno(+)
and e.empno = k2.empno(+)
and e.empno = 7839;
SELECT *
FROM TABLE(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST'));
------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem |
------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 10 | | | |
| 1 | MERGE JOIN OUTER | | 1 | 1 | 1 |00:00:00.01 | 10 | | | |
| 2 | MERGE JOIN OUTER | | 1 | 1 | 1 |00:00:00.01 | 9 | | | |
|* 3 | TABLE ACCESS FULL | EMP | 1 | 1 | 1 |00:00:00.01 | 7 | | | |
| 4 | BUFFER SORT | | 1 | 1 | 1 |00:00:00.01 | 2 | 2048 | 2048 | 2048 (0)|
| 5 | TABLE ACCESS BY INDEX ROWID| EMP_KIND1 | 1 | 1 | 1 |00:00:00.01 | 2 | | | |
|* 6 | INDEX UNIQUE SCAN | PK_EMP_KIND1 | 1 | 1 | 1 |00:00:00.01 | 1 | | | |
| 7 | BUFFER SORT | | 1 | 1 | 0 |00:00:00.01 | 1 | 1024 | 1024 | |
| 8 | TABLE ACCESS BY INDEX ROWID | EMP_KIND2 | 1 | 1 | 0 |00:00:00.01 | 1 | | | |
|* 9 | INDEX UNIQUE SCAN | PK_EMP_KIND2 | 1 | 1 | 0 |00:00:00.01 | 1 | | | |
------------------------------------------------------------------------------------------------------------------------------------
โก๏ธ ํ๋ช
์ ์ฌ์์ ์กฐํํ๋ ค๊ณ ํ๋๋ฐ ์ ๊ท์ง์ธ์ง ๋น์ ๊ท์ง์ธ์ง ๋ชจ๋ฅด๊ธฐ๋๋ฌธ์ 3๊ฐ์ ํ
์ด๋ธ์ ์กฐ์ธํ ์ ๋ฐ์ ์๋ ์ํฉ์ด๋ค. outer join sign์ ์ด ์ด์ ๋ null๊ฐ์ด ๋์ค๋ ๊ฒ์ ๋ณด๋ ค๊ณ !
โก๏ธ ์ ๊ท์ง ์ฌ์ ๋ฒํธ๊ฐ ๋ค์ด์ค๋ฉด ๋น์ ๊ท์ง ์ฌ์์ด๋ ์กฐ์ธ์ ํ๋ฉด ์๋๊ณ , ๋น์ ๊ท์ง ์ฌ์์ ์ฌ์๋ฒํธ๊ฐ ๋ค์ด์ค๋ฉด ์ ๊ท์ง ์ฌ์ ํ
์ด๋ธ์ด๋ ์กฐ์ธ์ ํ๋ฉด ์๋๋๋ฐ ์ ์คํ๊ณํ๋ณด๋ฉด ๋ค ํ๊ณ ์๋ค. ๋ฒํผ๊ฐ 0์ด ์๋.
โ๏ธ ํ๋ ํ
select /*+ gather_plan_statistics*/ e.empno, e.ename, k1.office_sal, k2.sal from emp e, emp_kind1 k1, emp_kind2 k2 where decode(e.emp_kind,1, e.empno) = k1.empno(+) and (e.emp_kind,2, e.empno) = k2.empno(+) and e.empno = 7839;
(e.emp_kind,1, e.empno)1์ด๋ฉด ์ ๊ท์ง์ผ๊ฑฐ๊ณ 2 ์ด๋ฉด ๋น์ ๊ท์ง์ผ๊ฒ์ด๋ค. ์ ํ์ ์กฐ์ธ์ด ๋๊ฒ๋ ํ๋ค.-------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | -------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 9 | | 1 | NESTED LOOPS OUTER | | 1 | 1 | 1 |00:00:00.01 | 9 | | 2 | NESTED LOOPS OUTER | | 1 | 1 | 1 |00:00:00.01 | 9 | |* 3 | TABLE ACCESS FULL | EMP | 1 | 1 | 1 |00:00:00.01 | 7 | | 4 | TABLE ACCESS BY INDEX ROWID| EMP_KIND1 | 1 | 1 | 1 |00:00:00.01 | 2 | |* 5 | INDEX UNIQUE SCAN | PK_EMP_KIND1 | 1 | 1 | 1 |00:00:00.01 | 1 | | 6 | TABLE ACCESS BY INDEX ROWID | EMP_KIND2 | 1 | 1 | 0 |00:00:00.01 | 0 | |* 7 | INDEX UNIQUE SCAN | PK_EMP_KIND2 | 1 | 1 | 0 |00:00:00.01 | 0 | --------------------------------------------------------------------------------------------------------โก๏ธ ๋ฒํผ์ ๊ฐฏ์๊ฐ 0์ผ๋ก ๋ฐ๋์๋ค.
1. ์์ํ๊ฒ ์๋ธ์ฟผ๋ฆฌ๊ฐ ์คํ๋๋ SQL (no_unnest)
1) ์๋ธ์ฟผ๋ฆฌ ๋ถํฐ ์ํ๋๋๋ก ํ ์ ์์ (push_subq)
2) ๋ฉ์ธ์ฟผ๋ฆฌ ๋ถํฐ ์ํ๋๋ก๋ก ํ ์ ์์ (no_push_subq)
2. ์ฟผ๋ฆฌ ๋ณํ๊ธฐ์ ์ํด ์กฐ์ธ์ผ๋ก ๋ณ๊ฒฝ๋๋ SQL (unnest)
1) nested loop semi join (nl_sj)
2) hash semi join (hash_sj)
3) sort merge semi join (merge_sj)
4) nested loop anti join (nl_aj)
5) hash anti join (hash_aj)
6) sort merge anti join (merge_aj)
๋ฌธ์ 1. ์๋ SQL์ ์คํ๊ณํ์ ์์ํ๊ฒ ์๋ธ์ฟผ๋ฆฌ๋ก ์ํ๋๋๊ฐ ์๋๋ฉด ์กฐ์ธ์ผ๋ก ๋ณ๊ฒฝ์ด ๋์ด ์ํ๋๋๊ฐ??
select /*+ gather_plan_statistics*/ ename, sal from emp where deptno in (select deptno from dept where deptno=10); SELECT * FROM TABLE(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST')); ---------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem | ---------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 3 |00:00:00.01 | 10 | | | | |* 1 | HASH JOIN SEMI | | 1 | 3 | 3 |00:00:00.01 | 10 | 1557K| 1557K| 400K (0)| |* 2 | TABLE ACCESS FULL| EMP | 1 | 3 | 3 |00:00:00.01 | 7 | | | | |* 3 | TABLE ACCESS FULL| DEPT | 1 | 1 | 1 |00:00:00.01 | 3 | | | | ---------------------------------------------------------------------------------------------------------------- -- ํ๋ ํ select /*+ gather_plan_statistics*/ ename, sal from emp where deptno in (select /*+ no_unnest */ deptno from dept where deptno=10);
no_unnest๋ถ์ ์ด ๋๊ฐ๋ผ ๊ฐํ ๊ธ์ . ์ฌํ๊ฒ ๊ฐ์ธ๋ผ ! -> ์ฆ ์๋ธ์ฟผ๋ฆฌ๋ฅผ ํด์ฒดํด์ ์กฐ์ธ์ ํ์ง ๋ง๊ณ ์์ํ๊ฒ ์๋ธ์ฟผ๋ฆฌ๋ก ํ์ด๋ผ!
โก๏ธ ๋ฉ์ธ ์ฟผ๋ฆฌ๋ถํฐ ์ํ์ด ๋์๋ค.
๋ฌธ์ 2. ์ SQL์ ๋ฉ์ธ ์ฟผ๋ฆฌ๋ถํฐ ์ํ์ด ๋์๋๋ฐ, ์๋ธ์ฟผ๋ฆฌ๋ถํฐ ์ํ๋๊ฒ ํด๋ณด๊ธฐ
select /*+ gather_plan_statistics*/ ename, sal
from emp
where deptno in (select /*+ no_unnest push_subq */ deptno
from dept
where deptno=10);
โก๏ธ select /*+ no_unnest push_subq */ : ์๋ธ์ฟผ๋ฆฌ๋ถํฐ ์ํํด๋ผ
โก๏ธ select /*+ no_unnest no_push_subq */ : ๋ฉ์ธ์ฟผ๋ฆฌ๋ถํฐ ์ํํด๋ผ

๋ฌธ์ 3. ์๋์ SQL์ด ์์ํ๊ฒ ์๋ธ์ฟผ๋ฆฌ๋ก ์คํ๋๊ฒ ํ๋๋ฐ ์๋ธ์ฟผ๋ฆฌ๋ถํฐ ์ํ๋๊ฒ ํ๊ธฐ
-- ํ๋ ์
select ename, sal
from emp
where sal = (select max(sal)
from emp );
-- ํ๋ ํ
select /*+ gather_plan_statistics QB_NAME(main) */ ename, sal
from emp
where sal = (select /*+ no_unnest push_subq QB_NAME(sub) */ max(sal) from emp);
select * from table(dbms_xplan.display_cursor(format=>'advanced'));
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 6 (100)| |
|* 1 | TABLE ACCESS FULL | EMP | 1 | 20 | 3 (0)| 00:00:01 |
| 2 | SORT AGGREGATE | | 1 | 13 | | |
| 3 | TABLE ACCESS FULL| EMP | 14 | 182 | 3 (0)| 00:00:01 |
----------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - MAIN / EMP@MAIN
2 - SUB
3 - SUB / EMP@SUB
โก๏ธ QB_NAME ํํธ๋ ์ฟผ๋ฆฌ์ ์ด๋ฆ์ ์ง์ ํด์ฃผ๋ ํํธ์ด๋ค. ๊ดํธ ์์๋ ๋ง์๋๋ก ์จ๋ ๋จ!
์์ํ๊ฒ ์๋ธ์ฟผ๋ฆฌ๋ก ์ํ๋๋๊ฒ ๋๋ฆฌ๋ค๋ฉด ์กฐ์ธ์ผ๋ก ๋ณ๊ฒฝํ๋๊ฒ์ ๊ถ์ฅํ๋ค!!!
๋ฌธ์ 4. ์๋์ SQL์ ์กฐ์ธ์ผ๋ก ์ํ๋๊ฒ๋ ํํธ๋ฅผ ์ฃผ๊ธฐ!
select ename, sal
from emp
where deptno in (select deptno
from emp
where loc = 'DALLAS');
SELECT *
FROM TABLE(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST'));
----------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem |
----------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 5 |00:00:00.01 | 14 | | | |
|* 1 | HASH JOIN SEMI | | 1 | 5 | 5 |00:00:00.01 | 14 | 1557K| 1557K| 625K (0)|
| 2 | TABLE ACCESS FULL| EMP | 1 | 14 | 14 |00:00:00.01 | 7 | | | |
|* 3 | TABLE ACCESS FULL| DEPT | 1 | 1 | 1 |00:00:00.01 | 7 | | | |
----------------------------------------------------------------------------------------------------------------
select /*+ gather_plan_statistics */ ename, sal from emp where deptno in (select/*+ unnest nl_sj */ deptno from dept where loc = 'DALLAS'); ------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | ------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 5 |00:00:00.01 | 24 | | 1 | NESTED LOOPS SEMI | | 1 | 5 | 5 |00:00:00.01 | 24 | | 2 | TABLE ACCESS FULL| EMP | 1 | 14 | 14 |00:00:00.01 | 7 | |* 3 | TABLE ACCESS FULL| DEPT | 3 | 1 | 1 |00:00:00.01 | 17 | -------------------------------------------------------------------------------------โก๏ธ SEMI JOIN์ํ๋ค. SEMI์ ๋ป์ด ์ ๋ฐ ์ด๋ผ๋ ๋ป์ด์๋ค. ์์ ํ ์กฐ์ธ์ ์กฐ์ธ ์์์ ์กฐ์ธ ๋ฐฉ๋ฒ์ ์์ ๋กญ๊ฒ ํํธ๋ฅผ ํตํด ๊ฒฐ์ ํ ์ ์๋๋ฐ semi ์กฐ์ธ์ ์กฐ์ธ ๋ฐฉ๋ฒ์ ์์ ๋กญ๊ฒ ํํธ๋ฅผ ํตํด ์ง์ ํ ์ ์๋๋ฐ ์กฐ์ธ ์์๋ฅผ ๋ชป๋ฐ๊พผ๋ค. ๋ฌด์กฐ๊ฑด ๋ฉ์ธ์ฟผ๋ฆฌ๋ถํฐ ์ํ๋๊ธฐ ๋๋ฌธ์ ์ ๋ฐ์ ์กฐ์ธ์ด๋ค. ํด์ฌ ์ธ๋ฏธ ์กฐ์ธ๋ง ์กฐ์ธ ์์๋ฅผ ์กฐ์ ํ ์ ์๋ค.
๋ฌธ์ 5. ์๋์ SQL์ ํด์ฌ ์ธ๋ฏธ ์กฐ์ธ์ผ๋ก ์ํ๋๊ฒ ํ๊ธฐ
select /*+ gather_plan_statistics */ ename, sal
from emp
where deptno in (select/*+ unnest nl_sj */ deptno
from dept
where loc = 'DALLAS');
select /*+ gather_plan_statistics */ ename, sal from emp where deptno in (select/*+ unnest hash_sj */ deptno from dept where loc = 'DALLAS'); ---------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem | ---------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 5 |00:00:00.01 | 14 | | | | |* 1 | HASH JOIN SEMI | | 1 | 5 | 5 |00:00:00.01 | 14 | 1557K| 1557K| 647K (0)| | 2 | TABLE ACCESS FULL| EMP | 1 | 14 | 14 |00:00:00.01 | 7 | | | | |* 3 | TABLE ACCESS FULL| DEPT | 1 | 1 | 1 |00:00:00.01 | 7 | | | | ----------------------------------------------------------------------------------------------------------------โก๏ธ ์ง๊ธ hash table์ด emp ์ด๋ค. ๊ทผ๋ฐ dept๊ฐ ์ฌ๋ผ๊ฐ์ผํจ
๋ฌธ์ 6. ์ SQL์ ํด์ฌ ํ
์ด๋ธ์ด dept๊ฐ ๋๊ฒ ํ๊ธฐ
select /*+ gather_plan_statistics */ ename, sal from emp where deptno in (select/*+ unnest hash_sj swap_join_inputs(dept) */ deptno from dept where loc = 'DALLAS'); ------------------------------------------------------------------------------------------------------------------ | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem | ------------------------------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | | 5 |00:00:00.01 | 14 | | | | |* 1 | HASH JOIN RIGHT SEMI| | 1 | 5 | 5 |00:00:00.01 | 14 | 2440K| 2440K| 712K (0)| |* 2 | TABLE ACCESS FULL | DEPT | 1 | 1 | 1 |00:00:00.01 | 7 | | | | | 3 | TABLE ACCESS FULL | EMP | 1 | 14 | 14 |00:00:00.01 | 7 | | | | ------------------------------------------------------------------------------------------------------------------โก๏ธ ํํธ๋ ์๋ธ์ฟผ๋ฆฌ์ชฝ์ ์ฃผ๊ธฐ
๋ฌธ์ 7. ์๋ SQL์ ํ๋ํ๊ธฐ
select /*+ gather_plan_statistics */ ename, sal
from emp
where deptno not in (select deptno
from dept
where loc='DALLAS');
----------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem |
----------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 9 |00:00:00.01 | 14 | | | |
|* 1 | HASH JOIN ANTI NA | | 1 | 14 | 9 |00:00:00.01 | 14 | 1557K| 1557K| 649K (0)|
| 2 | TABLE ACCESS FULL| EMP | 1 | 14 | 14 |00:00:00.01 | 7 | | | |
|* 3 | TABLE ACCESS FULL| DEPT | 1 | 1 | 1 |00:00:00.01 | 7 | | | |
----------------------------------------------------------------------------------------------------------------
โก๏ธ ์๋ธ์ฟผ๋ฆฌ๊ฐ ์กฐ์ธ์ผ๋ก ํ๋ฆด ๋ not in์ ์ฌ์ฉํ์ผ๋ฉด anti join์ด ๋๋ค. ์๋ธ์ฟผ๋ฆฌ๊ฐ ์กฐ์ธ์ผ๋ก ํ๋ฆด ๋ in์ ์ฌ์ฉํ์ผ๋ฉด semi join์ด ๋์จ๋ค.
์ ์คํ๊ณํ์์ ํด์ฌ ํ
์ด๋ธ์ด dept๊ฐ ์๋๋ผ emp์ฌ์ ํ๋์ด ํ์ํ ๊ฒ์ด๋ค.
โ๏ธ deptํ ์ด๋ธ์ด ํด์ฌ ํ ์ด๋ธ์ด ๋๋๋ก ํ๋!!
select /*+ gather_plan_statistics */ ename, sal from emp where deptno not in (select /*+ unnest hash_aj swap_join_inputs(dept) */ deptno from dept where loc='DALLAS' and deptno is not null) and deptno is not null;โก๏ธ
not in์ผ๋ก ์ด ์๋ธ์ฟผ๋ฆฌ๊ฐ ๊ต์ฅํ ๋๋ฆด ๋and deptno is not null์ ๊ผญ ์ถ๊ฐํ๊ธฐ.
๋ฌธ์ 8. ์๋์ SQL์ ํ๋ํ๊ธฐ
-- customers100 ๋ง๋ค๊ธฐ
create table customers100 as select * from sh.customers;
create table sales100 as select * from sh.sales;
-- ํ๋ ์
select /*+ gather_plan_statistics */ count(*)
from customers100 c
where c.cust_id not in (select /*+ no_unnest push_subq */ cust_id
from sales100
where amount_sold between 0 and 10000);
โ๏ธ ํ๋ ํ
select /*+ gather_plan_statistics */ count(*) from customers100 c where c.cust_id not in (select /*+ unnest hash_aj */ cust_id from sales100 where amount_sold between 0 and 10000); ---------------------------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads | OMem | 1Mem | Used-Mem | ---------------------------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.40 | 5852 | 5845 | | | | | 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.40 | 5852 | 5845 | | | | |* 2 | HASH JOIN ANTI NA | | 1 | 48304 | 47799 |00:00:00.40 | 5852 | 5845 | 4010K| 3056K| 4596K (0)| | 3 | TABLE ACCESS FULL| CUSTOMERS100 | 1 | 48304 | 54288 |00:00:00.03 | 1416 | 1413 | | | | |* 4 | TABLE ACCESS FULL| SALES100 | 1 | 712K| 918K|00:00:00.18 | 4436 | 4432 | | | | ----------------------------------------------------------------------------------------------------------------------------------โก๏ธ
swap_join_inputs์์จ์ where ๋ฐ์ ์กฐ๊ฑด ๋นผ์ฃผ์๋ค.
1. merge: view, in line view๋ฅผ ํ์ดํด์ณ๋ผ
2. no_merge: view, in line view๋ฅผ ํ์ดํด์น์ง ๋ง์๋ผ
select /*+ gather_plan_statistics */ v.ename, v.loc, s.grade
from salgrade s, (select e.ename, d.loc, e.sal, e.deptno
from emp e, dept d
where e.deptno = d.deptno ) v
where v.sal between s.losal and s.hisal;

โก๏ธ ์คํ๊ณํ์์ ๋ทฐ๊ฐ ์๋์ค๋ ์ด์ ๋ ์ฟผ๋ฆฌ ๋ณํ๊ธฐ๊ฐ in line view๋ฅผ ํด์ฒดํด์ ์ด๋ค. ์ฟผ๋ฆฌ ๋ณํ๊ธฐ๊ฐ ์๋์ ๊ฐ์ด SQL์ ๋ณ๊ฒฝํ๋ค. ๋ทฐ๋ฅผ ํด์ฒดํ์ง ๋ง๋ผ๊ณ ํด์ผํ๋ค !!! no_merge
select e.ename, d.loc, s.grade
from emp e, dept d, salgrade s
where e.deptno=d.deptno and e.sal between s.losal and s.hisal;
-- ํํธ ์ฌ์ฉํ๊ธฐ
select /*+ gather_plan_statistics no_merge(v) */ v.ename, v.loc, s.grade
from salgrade s, (select e.ename, d.loc, e.sal, e.deptno
from emp e, dept d
where e.deptno = d.deptno ) v
where v.sal between s.losal and s.hisal;
------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem |
------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 14 |00:00:00.01 | 20 | | | |
| 1 | MERGE JOIN | | 1 | 1 | 14 |00:00:00.01 | 20 | | | |
| 2 | SORT JOIN | | 1 | 5 | 5 |00:00:00.01 | 6 | 2048 | 2048 | 2048 (0)|
| 3 | TABLE ACCESS FULL | SALGRADE | 1 | 5 | 5 |00:00:00.01 | 6 | | | |
|* 4 | FILTER | | 5 | | 14 |00:00:00.01 | 14 | | | |
|* 5 | SORT JOIN | | 5 | 14 | 40 |00:00:00.01 | 14 | 2048 | 2048 | 2048 (0)|
| 6 | VIEW | | 1 | 14 | 14 |00:00:00.01 | 14 | | | |
|* 7 | HASH JOIN | | 1 | 14 | 14 |00:00:00.01 | 14 | 1696K| 1696K| 1071K (0)|
| 8 | TABLE ACCESS FULL| DEPT | 1 | 4 | 4 |00:00:00.01 | 7 | | | |
| 9 | TABLE ACCESS FULL| EMP | 1 | 14 | 14 |00:00:00.01 | 7 | | | |
------------------------------------------------------------------------------------------------------------------------
โ๏ธ ์ธ๋ผ์ธ๋ทฐ ๋ง๊ณ ์ง์ง view๋ง๋ค๊ธฐ
create or replace view emp142
as
select e.ename, d.loc, e.sal, e.deptno
from emp e, dept d
where e.deptno = d.deptno;
โ๏ธ view๋ ์กฐ์ธํ๊ธฐ
select /*+ gather_plan_statistics */ v.ename, v.loc, s.grade
from emp142 v, salgrade s
where v.sal between s.losal and s.hisal;
>
-----------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem |
-----------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 14 |00:00:00.01 | 20 | | | |
|* 1 | HASH JOIN | | 1 | 1 | 14 |00:00:00.01 | 20 | 1557K| 1557K| 663K (0)|
| 2 | MERGE JOIN | | 1 | 1 | 14 |00:00:00.01 | 13 | | | |
| 3 | SORT JOIN | | 1 | 5 | 5 |00:00:00.01 | 6 | 2048 | 2048 | 2048 (0)|
| 4 | TABLE ACCESS FULL | SALGRADE | 1 | 5 | 5 |00:00:00.01 | 6 | | | |
|* 5 | FILTER | | 5 | | 14 |00:00:00.01 | 7 | | | |
|* 6 | SORT JOIN | | 5 | 14 | 40 |00:00:00.01 | 7 | 2048 | 2048 | 2048 (0)|
| 7 | TABLE ACCESS FULL| EMP | 1 | 14 | 14 |00:00:00.01 | 7 | | | |
| 8 | TABLE ACCESS FULL | DEPT | 1 | 4 | 4 |00:00:00.01 | 7 | | | |
-----------------------------------------------------------------------------------------------------------------------
โก๏ธ ๋ทฐ๋ฅผ ํด์ฒดํ๋ค
โ๏ธ ๊ทธ๋ ๋ค๋ฉด view๋ฅผ ํด์ฒดํ์ง ์๊ฒ ํ๊ธฐ
select /*+ gather_plan_statistics no_merge(v) */ v.ename, v.loc, s.grade from emp142 v, salgrade s where v.sal between s.losal and s.hisal; ------------------------------------------------------------------------------------------------------------------------ | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem | ------------------------------------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | | 14 |00:00:00.01 | 20 | | | | | 1 | MERGE JOIN | | 1 | 1 | 14 |00:00:00.01 | 20 | | | | | 2 | SORT JOIN | | 1 | 5 | 5 |00:00:00.01 | 6 | 2048 | 2048 | 2048 (0)| | 3 | TABLE ACCESS FULL | SALGRADE | 1 | 5 | 5 |00:00:00.01 | 6 | | | | |* 4 | FILTER | | 5 | | 14 |00:00:00.01 | 14 | | | | |* 5 | SORT JOIN | | 5 | 14 | 40 |00:00:00.01 | 14 | 2048 | 2048 | 2048 (0)| | 6 | VIEW | EMP142 | 1 | 14 | 14 |00:00:00.01 | 14 | | | | |* 7 | HASH JOIN | | 1 | 14 | 14 |00:00:00.01 | 14 | 1696K| 1696K| 1071K (0)| | 8 | TABLE ACCESS FULL| DEPT | 1 | 4 | 4 |00:00:00.01 | 7 | | | | | 9 | TABLE ACCESS FULL| EMP | 1 | 14 | 14 |00:00:00.01 | 7 | | | | ------------------------------------------------------------------------------------------------------------------------
๋ฌธ์ 2. ์ ์คํ๊ณํ์ view ์์ ํ
์ด๋ธ์ ์กฐ์ธ ์์๋ฅผ emp -> dept์์ด ๋๊ฒ ํ๊ธฐ
select /*+ gather_plan_statistics no_merge(v) leading(v.e v.d) */ v.ename, v.loc, s.grade
from emp142 v, salgrade s
where v.sal between s.losal and s.hisal;
------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem |
------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 14 |00:00:00.01 | 20 | | | |
| 1 | MERGE JOIN | | 1 | 1 | 14 |00:00:00.01 | 20 | | | |
| 2 | SORT JOIN | | 1 | 5 | 5 |00:00:00.01 | 6 | 2048 | 2048 | 2048 (0)|
| 3 | TABLE ACCESS FULL | SALGRADE | 1 | 5 | 5 |00:00:00.01 | 6 | | | |
|* 4 | FILTER | | 5 | | 14 |00:00:00.01 | 14 | | | |
|* 5 | SORT JOIN | | 5 | 14 | 40 |00:00:00.01 | 14 | 2048 | 2048 | 2048 (0)|
| 6 | VIEW | EMP142 | 1 | 14 | 14 |00:00:00.01 | 14 | | | |
|* 7 | HASH JOIN | | 1 | 14 | 14 |00:00:00.01 | 14 | 1557K| 1557K| 662K (0)|
| 8 | TABLE ACCESS FULL| EMP | 1 | 14 | 14 |00:00:00.01 | 7 | | | |
| 9 | TABLE ACCESS FULL| DEPT | 1 | 4 | 4 |00:00:00.01 | 7 | | | |
------------------------------------------------------------------------------------------------------------------------
๋ฌธ์ 3. (์ ์ฒด ๊ณผ์ ์ ๋ง์ง๋ง ๋ฌธ์ ) ์ SQL์ ์คํ ๊ณํ์ด ์๋์ ๊ฐ์ด ์ถ๋ ฅ๋๊ฒ ํ๊ธฐ
select /*+ gather_plan_statistics no_merge(v) leading(v.e v.d) leading(v s) use_nl(s) */ v.ename, v.loc, s.grade
from emp142 v, salgrade s
where v.sal between s.losal and s.hisal;
