show parameter PLSQL
NAME | TYPE | VALUE |
plsql_v2_compatibility | 1 | FALSE |
plsql_warnings | 2 | DISABLE:ALL |
plsql_code_type | 2 | INTERPRETED |
plsql_debug | 1 | FALSE |
plsql_optimize_level | 3 | 2 |
plsql_ccflags | 2 |
사용자 정의 함수 남용(날짜형을 문자열 포멧으로 변환)
create or replace function date_to_char(p_dt date) return varchar2
as
begin
return to_char(p_dt, 'yyyy/mm/dd hh24:mi:ss');
end;
/
create table t ( no number, char_time varchar2(21) ) ;
insert into t
select rownum no
, to_char(sysdate + rownum, 'yyyy/mm/dd hh24:mi:ss') char_time
from dual
connect by level <= 1000000 ;
경 과: 00:00:03.88
insert into t
select rownum no
, date_to_char(sysdate + rownum) char_time
from dual
connect by level <= 1000000 ;
경 과: 00:00:12.24
create or replace function date_to_char(p_dt date) return varchar2
as
n number;
begin
select 1 into n from dual;
return to_char(p_dt, 'yyyy/mm/dd hh24:mi:ss');
end;
/
insert into t
select rownum no
, date_to_char(sysdate + rownum) char_time
from dual
connect by level <= 1000000 ;
경 과: 00:00:35.79
SELECT 1
FROM DUAL
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1000000 15.18 14.21 0 0 0 0
Fetch 1000000 15.35 13.79 0 0 0 1000000
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 2000001 30.54 28.00 0 0 0 1000000
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 61 (recursive depth: 1)
Rows Row Source Operation
-------- ----------------------------
1000000 FAST DUAL (cr=0 pr=0 pw=0 time=10983723 us)
함수사용의 제한
-- emp 테이블을 읽어 평균 급여를 리턴하는 함수 생성
SQL> create or replace function emp_avg_sal return number
2 is
3 l_avg_sal number;
4 begin
5 select avg(sal) into l_avg_sal from emp;
6 return l_avg_sal;
7 end;
8 /
--컬럼 구성을 달리하는 index 4개 생성
SQL> create index emp_x10 on emp(sal);
SQL> create index emp_x20 on emp(deptno);
SQL> create index emp_x30 on emp(deptno, sal);
SQL> create index emp_x40 on emp(deptno, ename, sal);
< 케이스 1 > : 인덱스를 사용하지 않고 Full Scan (전체 건수만큼 함수 호출)
select /*+ full(emp) */ * from emp
where sal >= emp_avg_sal ;
SELECT AVG(SAL) FROM EMP
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 14 0.00 0.00 0 0 0 0
Fetch 14 0.00 0.00 0 42 0 14
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 29 0.00 0.00 0 42 0 14
< 케이스 2 > : sal 컬럼을 선두로 갖는 인덱스를 이용 , 단 한번만 함수 호출(함수 먼저 실행하고 리턴된 값으로 EMP_X01 인덱스 엑세스 하는 상수 조건으로 사용)
select /*+ index(emp (sal)) */ * from emp
where sal > = emp_avg_sal;
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 1 0.00 0.00 0 3 0 1
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 3 0.00 0.00 0 3 0 1
< 케이스 3 > : 조건절에 deptno 컬럼 하나로 구성된 emp_x20 인덱스 이용
select /*+ index(emp, emp_x20) */ * from emp
where sal >= emp_avg_sal and deptno = 20;
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 5 0.00 0.00 0 0 0 0
Fetch 5 0.00 0.00 1 15 0 5
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 11 0.00 0.00 1 15 0 5
Predicate Information (identified by operation id):
---------------------------------------------------
# - filter("SAL">="EMP_AVG_SAL"())
# - access("DEPTNO"=20)
< 케이스 4 > : deptno +sal 순으로 구성된 emp_x30 인덱스 이용 (함수 호출이 한번 )
select /* index(emp (deptno, sal)) */ * from emp
where sal >= emp_avg_sal
and deptno = 20 ;
Predicate Information (identified by operation id):
---------------------------------------------------
# - access("DEPTNO"=20 AND "SAL">="EMP_AVG_SAL"() AND "SAL" IS NOT NULL)
Call Count CPU Time Elapsed Time Disk Query Current Rows
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Parse 1 0.000 0.000 0 0 0 0
Execute 1 0.000 0.000 0 0 0 0
Fetch 1 0.000 0.000 0 7 0 1
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Total 3 0.000 0.000 0 7 0 1
< 케이스 5 > : deptno와 sal 중간에 ename 컴럼이 낀 emp_x40 인덱스 사용 (함수호출 6번)
select /*+ index(emp (deptno, ename, sal)) */ * from emp
where sal >= emp_avg_sal
and deptno = 20;
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("DEPTNO"=20 AND "SAL">="EMP_AVG_SAL"())
filter("SAL">="EMP_AVG_SAL"())
Call Count CPU Time Elapsed Time Disk Query Current Rows
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Parse 1 0.000 0.001 0 0 0 0
Execute 6 0.000 0.000 0 0 0 0
Fetch 6 0.000 0.000 0 42 0 6
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Total 13 0.000 0.002 0 42 0 6
< 케이스 6 >
select /*+ index(emp (deptno, sal)) */ * from emp
where sal >= emp_avg_sal
and deptno >= 10 ;
2 - access("DEPTNO">=10 AND "SAL">="EMP_AVG_SAL"() AND "DEPTNO" IS NOT NULL)
filter("SAL">="EMP_AVG_SAL"()
Call Count CPU Time Elapsed Time Disk Query Current Rows
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Parse 1 0.000 0.000 0 0 0 0
Execute 14 0.000 0.001 0 0 0 0
Fetch 14 0.000 0.001 0 98 0 14
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Total 29 0.000 0.002 0 98 0 14
대용량 테이블에서는 조건절과 인덱스 구성에 따라 성능차이 확연
create table LookupTable ( key number, value varchar2(100) ) ;
insert into LookupTable values( 1, 'YAMAHA' );
create or replace function lookup(l_input number) return varchar2
as
l_output LookupTable.value%TYPE;
begin
select value into l_output from LookupTable where key = l_input;
return l_output;
end;
프로시저, 패키지, 트리거를 사용할 때도 공통적으로 나타나는 현상으로 주의