SQL >create table t1 as select level as c1, decode(level, 10000, 'one','many') as c2
2 from dual connect by level <= 10000;
Table created.
SQL >create table t2 as select level as c1, 'x' as c2 from dual
2 connect by level <= 10000;
Table created.
SQL >create index t1_n1 on t1(c1);
Index created.
SQL >create index t1_n2 on t1(c2);
Index created.
SQL >create index t2_n1 on t2(c1);
Index created.
SQL >exec dbms_stats.gather_table_stats('oracle','t1',method_opt=>'for all columns size skewonly');
PL/SQL procedure successfully completed.
SQL >exec dbms_stats.gather_table_stats('oracle','t2');
PL/SQL procedure successfully completed.
DBMS_XPLAN.DISPLAY
함수를 통해 얻을 수 있다.SQL> explain plan for
select * from t1, t2 where t1.c1 = t2.c1 and t1.c2 = :b1;
SQL>select * from table(dbms_xplan.display);
ORACLE@CX3WAS1 >select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------
Plan hash value: 1838229974
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5000 | 75000 | 8 (13)| 00:00:01 |
|* 1 | HASH JOIN | | 5000 | 75000 | 8 (13)| 00:00:01 |
|* 2 | TABLE ACCESS FULL| T1 | 5000 | 45000 | 4 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL| T2 | 10000 | 60000 | 3 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("T1"."C1"="T2"."C1")
2 - filter("T1"."C2"=:B1)
16 rows selected
DBMS_XPLAN.DISPLAY_CURSOR
함수를 사용하는 것이다.SQL> select * from t1, t2 where t1.c1 = t2.c1 and t1.c2 = :b1;
SQL> select * from table(dbms_xplan.display_cursor);
dbms_xplan.display_cursor
는 v$session에 대한 접근 권한을 가지고 있어야 한다. 테스트는 다음과 같다.SQL >var b1 varchar2(10);
SQL >exec :b1 := 'one';
PL/SQL procedure successfully completed.
SQL >select * from oracle.t1 t1, oracle.t2 t2 where t1.c1 = t2.c1 and t1.c2 = :b1;
C1 C2 C1 C
---------- ---- ---------- -
10000 one 10000 x
SQL >select * from table(dbms_xplan.display_cursor);
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------
SQL_ID 0mxyvwd9348p9, child number 0
-------------------------------------
select * from oracle.t1 t1, oracle.t2 t2 where t1.c1 = t2.c1 and t1.c2
= :b1
Plan hash value: 1838229974
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 8 (100)| |
|* 1 | HASH JOIN | | 5000 | 75000 | 8 (13)| 00:00:01 |
|* 2 | TABLE ACCESS FULL| T1 | 5000 | 45000 | 4 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL| T2 | 10000 | 60000 | 3 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("T1"."C1"="T2"."C1")
2 - filter("T1"."C2"=:B1)
22 rows selected.
DBMS_XPLAN.DISPLAY_CURSOR
함수는 V$SESSION 의 PREV_SQL_ID
컬럼과 PREV_CHILD_NUMBER
컬럼 값을 이용하여 방금 전에 실행한 쿼리를 인식한다. 그러므로, 방금전 실행한 쿼리의 정보를 가져올 필요가 없다.SQL> select * from t1, t2 where t1.c1 = t2.c1 and t1.c2 = :b1;
SQL> col prev_sql_id new_value prev_sql_id
SQL> col prev_child_number new_value prev_child_number
SQL> select prev_sql_id, prev_child_number from v$session where sid = userenv('sid');
SQL> select * from table( dbms_xplan.display_cursor ('&prev_sql_id' , '&prev_child_number'));
DBMS_XPLAN.DISPLAY_CURSOR
함수가 정상적으로 동작하지 않는다.SQL> set serveroutput on
SQL> select * from t1, t2 where t1.c1 = t2.c1 and t1.c2 = :b1;
SQL> select * from table(dbms_xplan.display_cursor);
SQL >set serveroutput on
SQL >select * from oracle.t1 t1, oracle.t2 t2 where t1.c1 = t2.c1 and t1.c2 = :b1;
C1 C2 C1 C
---------- ---- ---------- -
10000 one 10000 x
SQL >select * from table(dbms_xplan.display_cursor);
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------
SQL_ID 9babjv8yq8ru3, child number 0
BEGIN DBMS_OUTPUT.GET_LINES(:LINES, :NUMLINES); END;
NOTE: cannot fetch plan for SQL_ID: 9babjv8yq8ru3, CHILD_NUMBER: 0
Please verify value of SQL_ID and CHILD_NUMBER;
It could also be that the plan is no longer in cursor cache (check v$sql_plan)
8 rows selected
DBMS_XPLAN.DISPLAY_CURSOR
함수의 가장 큰 장점은 실행 계획 뿐아니라 일량 정보 (Plan Statistics)도 같이 보여준다는 것이다.GATHER_PLAN_STATISTICS
힌트를 부여하고 DBMS_XPLAN.DISPLAY_CURSOR
함수 호출 시 FORMAT 옵션에 "ALLSTATS LAST"값을 부여하면 된다.SQL_ID
와 CHILD_NUMBER
값이 null인 것은 현재 세션에서 방금 실행한 쿼리라는 의미이다.SQL> var b1 varchar2(10);
SQL> exec :b1 := 'one';
SQL> select /*+ gather_plan_statistics */ * from t1, t2
where t1.c1 = t2.c1 and t1.c2 = :b1;
SQL> select * from table(dbms_xplan.display_cursor(null, null, 'allstats last'));
SQL >var b1 varchar2(10);
SQL >exec :b1 := 'one';
PL/SQL procedure successfully completed.
SQL >select /*+ gather_plan_statistics */ * from oracle.t1 t1, oracle.t2 t2
2 where t1.c1 = t2.c1 and t1.c2 = :b1;
C1 C2 C1 C
---------- ---- ---------- -
10000 one 10000 x
SQL >select * from table(dbms_xplan.display_cursor(null, null, 'allstats last'));
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------
SQL_ID cnp2wr3gmdvgx, child number 0
-------------------------------------
select /*+ gather_plan_statistics */ * from oracle.t1 t1, oracle.t2 t2
where t1.c1 = t2.c1 and t1.c2 = :b1
Plan hash value: 1838229974
----------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem |
----------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 22 | | | |
|* 1 | HASH JOIN | | 1 | 5000 | 1 |00:00:00.01 | 22 | 1088K| 1088K| 416K (0)|
|* 2 | TABLE ACCESS FULL| T1 | 1 | 5000 | 1 |00:00:00.01 | 12 | | | |
| 3 | TABLE ACCESS FULL| T2 | 1 | 10000 | 10000 |00:00:00.02 | 10 | | | |
----------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("T1"."C1"="T2"."C1")
2 - filter("T1"."C2"=:B1)
22 rows selected.
SQL_ID
와 CHILD_NUMBER
를 합쳐야 한다.GATHER_PLAN_STATISTICS
힌트를 부여하고 쿼리를 실행하면 Plan Statistics가 계산된다.DBMS_XPLAN.DISPLAY_CURSOR
호출시 Plan Statistics정보를 얻을 수 없다.SQL >alter session set workarea_size_policy=manual;
Session altered.
SQL >alter session set sort_area_size = 0;
Session altered.
SQL >select /*+ gather_plan_statistics leading(oracle.t1) use_hash(oracle.t2) */
2 t1.c1, t2.c2 from oracle.t1 t1, oracle.t2 t2
3 where t1.c1 = t2.c1
4 and t1.c2 = 'many'
5 order by t1.c1, t1.c2;
...
9994 x
9995 x
9996 x
9997 x
9998 x
9999 x
9999 rows selected.
SQL >select * from table(dbms_xplan.display_cursor(null, null, 'allstats last'));
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------
SQL_ID 5yp2kdm32y34k, child number 0
-------------------------------------
select /*+ gather_plan_statistics leading(oracle.t1)
use_hash(oracle.t2) */ t1.c1, t2.c2 from oracle.t1 t1, oracle.t2 t2
where t1.c1 = t2.c1 and t1.c2 = 'many' order by t1.c1, t1.c2
Plan hash value: 2097371403
---------------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads | Writes | OMem | 1Mem | Used-Mem | Used-Tmp|
---------------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 9999 |00:00:00.05 | 25 | 29 | 29 | | | | |
| 1 | SORT ORDER BY | | 1 | 9999 | 9999 |00:00:00.05 | 25 | 29 | 29 | 234K| 234K| 193K (1)| 1024 |
|* 2 | HASH JOIN | | 1 | 9999 | 9999 |00:00:00.03 | 22 | 16 | 16 | 1156K| 1156K| 492K (1)| 1024 |
| 3 | TABLE ACCESS FULL| T2 | 1 | 10000 | 10000 |00:00:00.02 | 10 | 0 | 0 | | | | |
|* 4 | TABLE ACCESS FULL| T1 | 1 | 9999 | 9999 |00:00:00.02 | 12 | 0 | 0 | | | | |
---------------------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2 - access("T1"."C1"="T2"."C1")
4 - filter("T1"."C2"='many')
24 rows selected.
SQL >
V$SQL_PLAN_STATISTICS
에서 얻는 정보를 의미한다.SQL> desc v$sql_plan_statistics
V$SQL_WORKAREA
에서 얻은 정보이다.SQL> desc v$sql_workarea
V$SQL_WORKAREA
에서 검색해보면 DBMS_XPLAN.DISPLAY_CURSOR
함수와 동일한 결과를 얻을 수 있다.SQL> select * from v$sql_workarea where sql_id = 'XXX';
- 강좌 URL : http://www.gurubee.net/lecture/4277
- 구루비 강좌는 개인의 학습용으로만 사용 할 수 있으며, 다른 웹 페이지에 게재할 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^^
- 구루비 강좌는 서비스 제공을 위한 목적이나, 학원 홍보, 수익을 얻기 위한 용도로 사용 할 수 없습니다.