Post

<오라클 성능 고도화 원리와 해법1> Ch05-02 User Call vs. Recursive Call

오라클 성능 고도화 원리와 해법1 - Ch05-02 User Call vs. Recursive Call

앞에서는 데이터베이스 Call을 커서의 활동 상태에 따라 Parse, Execute, Fetch로 나누었는데, Call이 어디서 발생하느냐에 따라 User Call과 Recursive Call로 나눌 수도 있다.

SQL 트레이스 파일을 TKProf 유틸리티로 포맷팅하면 맨 아래쪽에 아래와 같은 Overall Total 통계가 나온다. 이 중 NON-RECURSIVE 통계가 User Call에 해당하며, 그 아래쪽 RECURSIVE 통계가 Recursive Call에 해당한다.

User Call은 OCI(Oracle Call Interface)를 통해 오라클 외부로부터 들어오는 Call을 말한다. 그림 5-2에서 User Call이 클라이언트가 아닌 WAS에서 발생하는 이유는, 실제 시스템 사용자가 어디에 위치하느냐는 별개로 DBMS 입장에서의 사용자는 WAS이기 때문이다. 그리고 위 그림 5-2는 개념적인 것으로서 실제 WAS가 DBMS와 같은 하드웨어 머신에 있을 수도 있다.

동시접속자수가 적을 때는 잘 드러나지 않지만 Peak 시간대에 시스템 장애를 발생시키는 가장 큰 주범은 뭐니 뭐니 해도 User Call이다. User Call이 많이 발생하도록 개발된 애플리케이션은 결코 좋은 성능을 낼 수 없으며, 이는 개발자의 기술력에 의해서도 좌우되지만 많은 경우 애플리케이션 설계와 프레임워크 기술 구조에 기인한다. 이를 테면, Array Processing을 제대로 지원하지 않는 프레임워크, 화면 페이지 처리에 대한 잘못 설계된 표준가이드, 사용자 정의 함수/프로시저에 대한 무조건적인 제약 등이 그것이다. 그리고 프로시저 단위 모듈을 지나치게 잘게 쪼개서 SQL을 건건이 호출하도록 설계하는 것도 대표적이다.

DBMS 성능과 확장성(Scalability)을 높이려면 User Call을 최소화하려는 노력이 무엇보다 중요하며, 이를 위해 아래와 같은 기능과 기술을 적극적으로 활용해야만 한다.

  1. Loop 쿼리를 해소하고 집합적 사고를 통해 One-SQL로 구현
  2. Array Processing: Array 단위 Fetch, Bulk Insert/Update/Delete
  3. 부분범위 처리 원리 활용
  4. 효과적인 화면 페이지 처리
  5. 사용자 정의 함수/프로시저/트리거의 적절한 활용

Recursive Call은 오라클 내부에서 발생하는 Call을 말한다. SQL 파싱과 최적화 과정에서 발생하는 Data Dictionary 조회, PL/SQL로 작성된 사용자 정의 함수/프로시저/트리거 내에서의 SQL 수행이 여기에 해당한다. Recursive Call을 최소화하려면, 바인드 변수를 적극적으로 사용해 하드 파싱 발생 횟수를 줄여야 한다. 그리고 PL/SQL로 작성한 프로그램이 어떤 특징을 가지며 내부적으로 어떻게 수행되는지를 잘 이해하고 시의적절하게 사용해야만 한다. 무조건 사용하지 못하도록 제약하거나 무분별하게 사용하지 말아야 한다는 뜻이다.

아래는 SQL 트레이스 결과에서 발췌한 것인데, recursive depth가 2로 표시돼 있다. 특정 프로시저를 호출했는데 거기서 또 다른 프로시저를 호출한 경우이며, 그 마지막 프로시저에서 사용된 SQL에 대한 수행 통계인 것이다. 이처럼 Recursive Depth가 깊어지도록 프로그래밍하는 것은 바람직하지 않다. PL/SQL은 가상머신(Virtual Machine) 상에서 수행되는 인터프리터(Interpreter) 언어이므로 빈번한 호출시 컨텍스트 스위칭(Context Switching) 때문에 성능이 매우 나빠진다. 성능을 위해서라면 PL/SQL 프로그램에 대한 지나친 모듈화는 지양해야 한다.

또한, 대용량 데이터 조회 쿼리에서 함수를 잘못 사용하면 건건이 함수 호출이 발생해 성능이 극도로 저하되는 경험을 많이 했을 것이다. 대용량 데이터를 조회할 때는 함수를 부분범위 처리가 가능한 상황에서 제한적으로 사용해야 하며, 될 수 있으면 조인 또는 스칼라 서브쿼리 형태로 변환하려는 노력이 필요하다. 여기까지만 설명하고, 함수 호출에 의한 부하해소 원리에 대해서는 7절 이하에서 자세히 다루기로 하겠다.

지금까지 설명한 데이터베이스 Call 종류와 앞으로 설명할 튜닝 원리를 간단히 요약하면 아래표와 같다.

This post is licensed under CC BY 4.0 by the author.