{section}
{column:width=50}
Table Full Scan 일량 확인
SQL> set pagesize 0
SQL> set linesize 130
SQL> SELECT /*+ gather_plan_statistics */
2 MAX(c1)
3 FROM t1
4 WHERE c2 = 'dummy'
5 ;
10000
SQL> SELECT * FROM TABLE(dbms_xplan.display_cursor(null,null,'allstats cost last'));
SQL_ID 0jgfqwmumc0y4, child number 0
-------------------------------------
SELECT /*+ gather_plan_statistics */ MAX(c1) FROM t1 WHERE c2 = 'dummy'
Plan hash value: 3724264953
--------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | Cost (%CPU)| A-Rows | A-Time | Buffers |
--------------------------------------------------------------------------------------------------
| 1 | SORT AGGREGATE | | 1 | 1 | | 1 |00:00:00.01 | 38 |
|* 2 | TABLE ACCESS FULL| T1 | 1 | 10000 | 12 (9)| 10000 |00:00:00.01 | 38 |
--------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("C2"='dummy')
18 개의 행이 선택되었습니다.
SQL> SELECT /*+ gather_plan_statistics */
2 MAX(c1)
3 FROM t1
4 WHERE c3 = 1
5 ;
10000
SQL> SELECT * FROM TABLE(dbms_xplan.display_cursor(null,null,'allstats cost last'));
SQL_ID 45aqvrk98b63j, child number 0
-------------------------------------
SELECT /*+ gather_plan_statistics */ MAX(c1) FROM t1 WHERE c3 = 1
Plan hash value: 3724264953
--------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | Cost (%CPU)| A-Rows | A-Time | Buffers |
--------------------------------------------------------------------------------------------------
| 1 | SORT AGGREGATE | | 1 | 1 | | 1 |00:00:00.01 | 38 |
|* 2 | TABLE ACCESS FULL| T1 | 1 | 1000 | 11 (0)| 1000 |00:00:00.01 | 38 |
--------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("C3"=1)
18 개의 행이 선택되었습니다.
{column}
{column:width=50}
{column}
{section}
{section}
{column:width=50}
Filter Operation 이 사용되었다면 일량은 얼마가 되어야 할까?
SQL> SELECT /*+ gather_plan_statistics */
2 *
3 FROM t1 y
4 WHERE c1 IN (SELECT /*+ NO_UNNEST */ MAX(c1) FROM t1 x WHERE x.c3 = y.c3 )
5 ;
9991 dummy 2
9992 dummy 3
9993 dummy 4
9994 dummy 5
9995 dummy 6
9996 dummy 7
9997 dummy 8
9998 dummy 9
9999 dummy 10
10000 dummy 1
10 개의 행이 선택되었습니다.
SQL> SELECT * FROM TABLE(dbms_xplan.display_cursor(null,null,'allstats cost last'));
SQL_ID 9thkv08ta6naz, child number 0
-------------------------------------
SELECT /*+ gather_plan_statistics */ * FROM t1 y WHERE c1 IN (SELECT /*+
NO_UNNEST */ MAX(c1) FROM t1 x WHERE x.c3 = y.c3 )
Plan hash value: 2626881942
---------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | Cost (%CPU)| A-Rows | A-Time | Buffers |
---------------------------------------------------------------------------------------------------
|* 1 | FILTER | | 1 | | | 10 |00:00:00.01 | 419 |
| 2 | TABLE ACCESS FULL | T1 | 1 | 10000 | 11 (0)| 10000 |00:00:00.01 | 39 |
| 3 | SORT AGGREGATE | | 10 | 1 | | 10 |00:00:00.01 | 380 |
|* 4 | TABLE ACCESS FULL| T1 | 10 | 1000 | 11 (0)| 10000 |00:00:00.01 | 380 |
---------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("C1"=)
4 - filter("X"."C3"=:B1)
22 개의 행이 선택되었습니다.
{column}
{column:width=50}
{column}
{section}
{section}
{column:width=50}
SQL> SELECT /*+ gather_plan_statistics */
2 *
3 FROM t1 y
4 WHERE c1 IN (SELECT /*+ NO_UNNEST */ MAX(c1) FROM t1 x WHERE x.c2 = y.c2 )
5 ;
10000 dummy 1
SQL> SELECT * FROM TABLE(dbms_xplan.display_cursor(null,null,'allstats cost last'));
SQL_ID 23x8b104hz9xd, child number 0
-------------------------------------
SELECT /*+ gather_plan_statistics */ * FROM t1 y WHERE c1 IN (SELECT /*+
NO_UNNEST */ MAX(c1) FROM t1 x WHERE x.c2 = y.c2 )
Plan hash value: 2626881942
---------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | Cost (%CPU)| A-Rows | A-Time | Buffers |
---------------------------------------------------------------------------------------------------
|* 1 | FILTER | | 1 | | | 1 |00:00:00.01 | 76 |
| 2 | TABLE ACCESS FULL | T1 | 1 | 10000 | 11 (0)| 10000 |00:00:00.01 | 38 |
| 3 | SORT AGGREGATE | | 1 | 1 | | 1 |00:00:00.01 | 38 |
|* 4 | TABLE ACCESS FULL| T1 | 1 | 10000 | 12 (9)| 10000 |00:00:00.01 | 38 |
---------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("C1"=)
4 - filter("X"."C2"=:B1)
22 개의 행이 선택되었습니다.
SQL>
{column}
{column:width=50}
{column}
{section}
{section}
{column:width=50}
Test용 Table
SQL> DROP TABLE t1 PURGE;
테이블이 삭제되었습니다.
SQL> -- 예시자료 생성 --
SQL> CREATE TABLE t1(c1 INT, c2 INT);
테이블이 생성되었습니다.
SQL> INSERT INTO t1
2 SELECT MOD(level, 10) + 1 c1 -- 10개값(1~10)
3 , level c2 -- 유일값(1~1000)
4 FROM dual
5 CONNECT BY level <= 1000
6 ;
1000 개의 행이 만들어졌습니다.
SQL> COMMIT;
커밋이 완료되었습니다.
SQL> -- 패키지 변수 생성 --
SQL> CREATE OR REPLACE PACKAGE p1 AS g_idx INT := 0; END;
2 /
패키지가 생성되었습니다.
SQL> -- Deterministic Function 생성 --
SQL> CREATE OR REPLACE FUNCTION f1(v1 INT)
2 RETURN NUMBER
3 DETERMINISTIC
4 IS
5 BEGIN
6 p1.g_idx := p1.g_idx + 1;
7 RETURN 1;
8 END;
9 /
함수가 생성되었습니다.
{column}
{column:width=50}
{column}
{section}
{section}
{column:width=50}
함수 호출 테스트 : 쿼리
SQL> -- 함수 호출 테스트 : 쿼리 --
SQL> set serveroutput on
SQL> EXEC p1.g_idx := 0;
PL/SQL 처리가 정상적으로 완료되었습니다.
SQL> SELECT f1(c1) FROM t1 WHERE ROWNUM <= 100;
1
100 개의 행이 선택되었습니다.
SQL> EXEC dbms_output.put_line('count = 100, call = ' || p1.g_idx);
count = 100, call = 70
PL/SQL 처리가 정상적으로 완료되었습니다.
{column}
{column:width=50}
{column}
{section}
{section}
{column:width=50}
함수 호출 테스트 : PL/SQL
SQL> -- 함수 호출 테스트 : PL/SQL --
SQL> DECLARE
2 v_count NUMBER;
3 BEGIN
4 FOR idx IN 1..100 LOOP
5 p1.g_idx := 0;
6 FOR r IN (SELECT f1(c1) FROM t1 WHERE ROWNUM <= idx) LOOP
7 null;
8 END LOOP;
9 dbms_output.put_line('count = ' || idx || ', call = ' || p1.g_idx);
10 END LOOP;
11 END;
12 /
count = 1, call = 1
count = 2, call = 2
count = 3, call = 3
count = 4, call = 4
count = 5, call = 5
count = 6, call = 6
count = 7, call = 7
count = 8, call = 8
count = 9, call = 9
count = 10, call = 10
count = 11, call = 10
count = 12, call = 10
...
count = 97, call = 10
count = 98, call = 10
count = 99, call = 10
count = 100, call = 10
PL/SQL 처리가 정상적으로 완료되었습니다.
{column}
{column:width=50}
{column}
{section}
{section}
{column:width=50}
Fetch Size 증가 후 함수 호출 테스트 : 쿼리
SQL> -- Fetch Size 증가 후 함수 호출 테스트 : 쿼리 --
SQL> set arraysize 1000
SQL> EXEC p1.g_idx := 0;
PL/SQL 처리가 정상적으로 완료되었습니다.
SQL> SELECT f1(c1) FROM t1 WHERE ROWNUM <= 100;
1
100 개의 행이 선택되었습니다.
SQL> EXEC dbms_output.put_line('count = 100, call = ' || p1.g_idx);
count = 100, call = 11
PL/SQL 처리가 정상적으로 완료되었습니다.
{column}
{column:width=50}
{column}
{section}
{section}
{column:width=50}
Fetch Size 낮춘 후 함수 호출 테스트 : 쿼리
SQL> -- Fetch Size 낮춘 후 함수 호출 테스트 : 쿼리 --
SQL> set arraysize 1
SQL> EXEC p1.g_idx := 0;
PL/SQL 처리가 정상적으로 완료되었습니다.
SQL> SELECT f1(c1) FROM t1 WHERE ROWNUM <= 100;
1
100 개의 행이 선택되었습니다.
SQL> EXEC dbms_output.put_line('count = 100, call = ' || p1.g_idx);
count = 100, call = 100
PL/SQL 처리가 정상적으로 완료되었습니다.
{column}
{column:width=50}
{column}
{section}
{section}
{column:width=50}
서브쿼리를 이용한 함수 호출 테스트 : 쿼리
SQL> -- 서브쿼리를 이용한 함수 호출 테스트 : 쿼리 --
SQL> set arraysize 1
SQL> EXEC p1.g_idx := 0;
PL/SQL 처리가 정상적으로 완료되었습니다.
SQL> SELECT (SELECT f1(c1) FROM dual) FROM t1 WHERE ROWNUM <= 100;
1
100 개의 행이 선택되었습니다.
SQL> EXEC dbms_output.put_line('count = 100, call = ' || p1.g_idx);
count = 100, call = 10
PL/SQL 처리가 정상적으로 완료되었습니다.
SQL>
{column}
{column:width=50}
{column}
{section}