Post

<오라클 성능 고도화 원리와 해법1> Ch05-01 Call 통계

오라클 성능 고도화 원리와 해법1 - Ch05-01 Call 통계

아래는 SQL 트레이스 레포트에서 Call 통계(Statistics) 부분만을 발췌한 것이다. 이 레포트는 커서의 활동 상태를 Parse, Execute, Fetch 세 단계로 나누어 각각에 대한 수행 통계를 보여준다.

Parse Call은 커서를 파싱하는 과정에 대한 통계로서, 실행 계획을 생성하거나 찾는 과정에 관한 정보를 포함한다. Execute Call은 말 그대로 커서를 실행하는 단계에 대한 통계를 보여준다. Fetch Call은 select 문에서 실제 레코드를 읽어 사용자가 요구한 결과 집합을 반환하는 과정에 대한 통계를 보여준다.

Parse Call 최소화 및 최적화 원리에 대해서는 앞장에서 자세히 살펴보았다. 바인드 변수를 사용해서 Parse Call을 가볍게하는 방법, 세션 커서 캐싱을 통해 Parse Call을 더 가볍게하는 방법, 애플리케이션 커서 캐싱을 통해 Parse Call이 아예 발생하지 않게 하는 방법 등을 기억할 것이다. 위 트레이스 결과에서도 애플리케이션 커서 캐싱 기법을 사용했음을 알 수 있다(Parse Call = 1).

insert, update, delete, merge 등 DML 문은 Execute Call 시점에 모든 처리 과정을 서버 내에서 완료하고 처리 결과만 리턴하므로 Fetch Call이 전혀 발생하지 않는다. insert … select 문도 마찬가지다. 클라이언트로부터 명시적인 Fetch Call을 받지 않으며 서버 내에서 묵시적으로 Fetch가 이루어진다.

select 문 일 때 Execute Call 단계에서는 커서만 열고, 실제 데이터를 처리하는 과정은 모두 Fetch 단계에서 일어난다. 예를들어, 아래는 100만 건짜리 CUST 테이블을 group by 하는 쿼리인데, sort group by 는 Execute 단계에서 처리할 것으로 예상되지만 실제로는 Fetch 시점에 모든 처리가 일어났다. 실제 데이터를 액세스하면서 일을 시작하는 시점은 첫 번째 Fetch Call 인 것을 짐작할 수 있다.

for update 구문을 사용하면 Execute Call 단계에서 모든 레코드를 읽어 Lock을 설정한다. 아래는 10,000개 레코드를 갖는 테이블을 for update 구문을 사용해 쿼리한 결과인데, 사용자는 11번의 Fetch Call을 통해 101개 레코드만 Fetch하고 멈췄지만 Execute 단계에서 이미 Current 모드로 읽어 10,000개 레코드 전체에 대해 Lock을 설정했음을 알 수 있다.

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