{section}
{column:width=50}
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
SQL> drop table t1 purge;
테이블이 삭제되었습니다.
SQL> drop table t2 purge;
테이블이 삭제되었습니다.
SQL> drop table t3 purge;
테이블이 삭제되었습니다.
SQL> create table t1(c1 int, c2 char(10), c3 int);
테이블이 생성되었습니다.
SQL> create table t2(c1 int, c2 char(10), c3 int);
테이블이 생성되었습니다.
SQL> create table t3(c1 int, c2 char(10), c3 int);
테이블이 생성되었습니다.
SQL> create index t1_n1 on t1(c1);
인덱스가 생성되었습니다.
SQL> create index t2_n1 on t2(c1);
인덱스가 생성되었습니다.
SQL> create index t3_n1 on t3(c1);
인덱스가 생성되었습니다.
SQL> create index t1_n2 on t1(c3);
인덱스가 생성되었습니다.
SQL> create index t2_n2 on t2(c3);
인덱스가 생성되었습니다.
SQL> create index t3_n2 on t3(c3);
인덱스가 생성되었습니다.
-- 논의를 간단하게 하기 위해 다음과 같이 Cost Based Query Transformation 을 비활성화 한다.
SQL> ALTER SESSION SET "_optimizer_cost_based_transformation" = off;
세션이 변경되었습니다.
SQL> ALTER SESSION SET "_optimizer_push_pred_cost_based" = false;
세션이 변경되었습니다.
{column}
{column:width=50}
{column}
{section}
{section}
{column:width=50}
SQL> insert into t1
2 select level, 'dummy', mod(level, 100) from dual
3 connect by level <= 10000
4 ;
10000 개의 행이 만들어졌습니다.
SQL> insert into t2
2 select level, 'dummy', mod(level, 100) from dual
3 connect by level <= 1000
4 ;
1000 개의 행이 만들어졌습니다.
SQL> insert into t3
2 select level, 'dummy', mod(level, 100) from dual
3 connect by level <= 100
4 ;
100 개의 행이 만들어졌습니다.
SQL> commit;
커밋이 완료되었습니다.
SQL> EXEC dbms_stats.gather_table_stats(user, 'T1');
PL/SQL 처리가 정상적으로 완료되었습니다.
SQL> EXEC dbms_stats.gather_table_stats(user, 'T2');
PL/SQL 처리가 정상적으로 완료되었습니다.
SQL> EXEC dbms_stats.gather_table_stats(user, 'T3');
PL/SQL 처리가 정상적으로 완료되었습니다.
{column}
{column:width=50}
{column}
{section}
{section}
{column:width=50}
SQL> SELECT count(*)
2 FROM (
3 SELECT /*+ gather_plan_statistics */
4 t1.c1, v.c2
5 FROM
6 t1,
7 (SELECT /*+ no_merge */ c1, c2
8 FROM t2
9 WHERE c1 BETWEEN 1 AND 1000) v
10 WHERE
11 t1.c1 = v.c1
12 )
13 ;
1000
SQL> SELECT * FROM TABLE(dbms_xplan.display_cursor(null,null,'allstats cost last'));
SQL_ID gp8tnk7qwgcj8, child number 0
-------------------------------------
SELECT count(*) FROM ( SELECT /*+ gather_plan_statistics */ t1.c1,
v.c2 FROM t1, (SELECT /*+ no_merge */ c1, c2 FROM t2 WHERE
c1 BETWEEN 1 AND 1000) v WHERE t1.c1 = v.c1 )
Plan hash value: 3590297760
-----------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | Cost (%CPU)| A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem|
-----------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 10 (100)| 1 |00:00:00.02 | 33 | | ||
| 1 | SORT AGGREGATE | | 1 | 1 | | 1 |00:00:00.02 | 33 | | ||
|* 2 | HASH JOIN | | 1 | 1000 | 10 (10)| 1000 |00:00:00.02 | 33 | 1066K| 1066K| 1192K (0)|
| 3 | VIEW | | 1 | 1000 | 2 (0)| 1000 |00:00:00.01 | 8 | | ||
|* 4 | INDEX FAST FULL SCAN| T2_N1 | 1 | 1000 | 2 (0)| 1000 |00:00:00.01 | 8 | | ||
| 5 | INDEX FAST FULL SCAN | T1_N1 | 1 | 10000 | 7 (0)| 10000 |00:00:00.01 | 25 | | ||
-----------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("T1"."C1"="V"."C1")
4 - filter(("C1">=1 AND "C1"<=1000)) -- 교재에서는 access 처리 : INDEX RANGE SCAN 사용
{column}
{column:width=50}
{column}
{section}
SQL> SELECT count(*)
2 FROM (
3 SELECT /*+ gather_plan_statistics */
4 t1.c1, v.c2
5 FROM
6 t1,
7 (SELECT c1, c2
8 FROM t2
9 WHERE c1 BETWEEN 1 AND 1000) v
10 WHERE
11 t1.c1 = v.c1
12 )
13 ;
1000
SQL> SELECT * FROM TABLE(dbms_xplan.display_cursor(null,null,'allstats cost last'));
SQL_ID gc3pxkdxw3gvr, child number 0
-------------------------------------
SELECT count(*) FROM ( SELECT /*+ gather_plan_statistics */ t1.c1,
v.c2 FROM t1, (SELECT c1, c2 FROM t2 WHERE c1 BETWEEN 1 AND
1000) v WHERE t1.c1 = v.c1 )
Plan hash value: 856841256
----------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | Cost (%CPU)| A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem |
----------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 6 (100)| 1 |00:00:00.01 | 11 | | | |
| 1 | SORT AGGREGATE | | 1 | 1 | | 1 |00:00:00.01 | 11 | | | |
|* 2 | HASH JOIN | | 1 | 999 | 6 (17)| 1000 |00:00:00.01 | 11 | 1066K| 1066K| 1241K (0)|
|* 3 | INDEX FAST FULL SCAN| T2_N1 | 1 | 1000 | 2 (0)| 1000 |00:00:00.01 | 8 | | | |
|* 4 | INDEX RANGE SCAN | T1_N1 | 1 | 1000 | 3 (0)| 1000 |00:00:00.01 | 3 | | | |
----------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("T1"."C1"="C1")
3 - filter(("C1">=1 AND "C1"<=1000)) -- 교재에서는 access 처리 : INDEX RANGE SCAN 사용
4 - access("T1"."C1">=1 AND "T1"."C1"<=1000)
{column}
{column:width=50}
{column}
{section}
{section}
{column:width=50}
SELECT
t1.c1, t2.c2
FROM
t1, t2
WHERE
t1.c1 = t2.c1 AND
t1.c1 BETWEEN 1 AND 1000 AND
t2.c1 BETWEEN 1 AND 1000
;
998 dummy
999 dummy
1000 dummy
1000 개의 행이 선택되었습니다.
SQL> SELECT * FROM TABLE(dbms_xplan.display_cursor(null,null,'allstats cost last'));
SQL_ID ad7gwucmhnq9z, child number 0
-------------------------------------
SELECT t1.c1, t2.c2 FROM t1, t2 WHERE t1.c1 = t2.c1 AND t1.c1
BETWEEN 1 AND 1000 AND t2.c1 BETWEEN 1 AND 1000
Plan hash value: 1733838511
------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | Cost (%CPU)| A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem |
------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 7 (100)| 1000 |00:00:00.01 | 77 | | | |
|* 1 | HASH JOIN | | 1 | 999 | 7 (15)| 1000 |00:00:00.01 | 77 | 1066K| 1066K| 1225K (0)|
|* 2 | INDEX RANGE SCAN | T1_N1 | 1 | 1000 | 3 (0)| 1000 |00:00:00.01 | 3 | | | |
|* 3 | TABLE ACCESS FULL| T2 | 1 | 1000 | 3 (0)| 1000 |00:00:00.01 | 74 | | | |
------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("T1"."C1"="T2"."C1")
2 - access("T1"."C1">=1 AND "T1"."C1"<=1000)
3 - filter(("T2"."C1">=1 AND "T2"."C1"<=1000))
{column}
{column:width=50}
{column}
{section}