PL/SQL로 작성한 함수와 프로시저를 컴파일 하면 JAVA처럼 BYTECODE가 생성이 된다.
PL/SQL 엔진만 있다면 어디서든 실행이 가능하다.
BYTECODE는 데이터 딕셔너리에 저장되었다가 런타임시 해석된다.
인터프리터 언어이므로 Native 코드로 완전 컴파일된 내장 함수에 비해 느리다.
함수 실행시 매번 SQL 실행엔진과 PL/SQL 가상버신 사이에 컨텍스트 스위칭이 일어난다.
(2) Recursive Call를 포함하지 않는 함수의 성능 부하
Recursive Call없이 컨텍스트 스위칭 효과만으로 보통 5~10 배 정도 느려진다.
(3)Recursive Call를 포함하는 함수의 성능 부하
사용자 정의 함수에는 Recursive Call을 포함하고, User Call에 비하면 비용이 훨씬 적지만 매번 Execute Call 과 Fetch Call을 발생시킨다.
대량의 데이터 조회시 레코드 단위로 함수를 호출하면 성능이 극도로 나빠진다.
p394, 395의 예를 보면 I/O가 전혀 발생하지 않는 가벼운 쿼리 (10g 이후 DUAL테이블을 쿼리하면 FAST DUAL방식으로 수행되므로 I/O가 전혀 발생하지 않음)를 삽입함에도 23배 가량 더 느려짐 그 원인으로는 데이터 베이스 CALL이 200만번이나 추가적으로 더 발생했기 때문
함수에서 발생하는 Recursive Call은 대부분 I/O를 수반함으로 훨씬 큰 성능저하를 가져옴
(4)함수를 필터 조건으로 사용할 때 주의 사항
Where절에서 필터 조건으로 사용할때도 조건절과 인덱스 상황에 따라 함수 호출 횟수가 달라진다.
(5)함수와 읽기 일관성
다른 세션에서 특정한 테이블의 값을 변경하면 쿼리수행중 중간부터 다른 결과 값을 리턴한다. 그 이유는 함수내에서 수행되는 Recursive 쿼리는 메인쿼리의 시작 시점과 무관하게 그 쿼리가 수행되는 시점을 기준으로 블록을 읽기 때문 :: 가장 기본적인 문장 수준 읽기(Statement-level consistency) 일관성이 보장이 되지 않는다.
Deterministic함수로 선언하거나 스칼라 서브쿼리를 덧씌우더라도 이 문제는 완전히 해결되지 않는다. 프로시저, 패키지, 트리거를 사용할 때도 공통적으로 나타나는 현상이다.
(6)함수의 올바른 사용기준
함수를 가급적 쓰지 말라는 의미는 아니며, 성능이 느려지는 원리를 잘 이해하고 잘 활용하라는 뜻임
개발 생산성만을 고려해 무분별 하게 함수를 남용했을때 생기는 부작용을 지적하고자 함이며,
채번 함수를 이용하여 성능을 향상시킬 수 있으며, 함수/프로시저를 사용하지 않았을 때 결국 User Call이 발생시키도록 구현한다면 오히려 오라클 함수/프로시저를 사용하는 것이 더 낫다.
Dependency체인에 의한 라이브러리 캐시 부하를 최소화 하려면 가급적 함수/프로시저 보다 패키지를 사용하는 것이 유리