07 PL/SQL 함수의 특징과 부하

(1) PL/SQL 함수의 특징

  • 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체인에 의한 라이브러리 캐시 부하를 최소화 하려면 가급적 함수/프로시저 보다 패키지를 사용하는 것이 유리
  • 역할을 분담하여 연산위주의 작업은 AP서버단에서 주로 처리하고
  • SQL 수행을 많이 요하는 작업은 오라클 함수/프로시저를 이용하도록 설계할 필요가 있다.