Parse Call 이란
흔히 말하는 Parsing = Parsing(파싱, parse count(total)) + Parse call(최적화, parse count(hard)) 를 말함.
이를 분리해야 하는 이유는
- Parse call 은 항상 발생 하지 않는다.
- 최적화를 위해서 반드시 parse call 이 필요한 것은 아니다.
- Parsing 을 위해서 반드시 parse call 이 필요한 것은 아니다.
- Parsing 과 최적화는 parse call 뿐만 아니라 execute call 단계에서도 발생
- Parse count(total) : 오라클커널에 의해 수행된 parse call 횟수 = SQL 수행 횟수
Bind variable test 시에는 PL/SQL cursor cache 효과(11g 이상 시만 )에 의해서 parse call 획기적으로 줄어듦
- Parse count(Hard) : 오라클이 문장을 최적화 한 횟수 = 최적화 횟수
- 문장에 대한 최적화(Parse count(hard)) 없이 parse call(parse count(total) 수행 가능
- 루프 내의 첫 번째 실행 시에, 오라클은 해당 문장에 대한 파싱 및 최적화 수행 후, 라이브러리 캐시 적재
- 루프 내의 두 번째 실행 시에, 오라클은파싱 및 최적화를 시작하기 전에 라이브러리 캐시를 검색하고, 동일 문장 존재 시, 최적화를 수행 하지 않고 재사용
cursor authentication
: 자식 커서의 내용을 비교 (동일 오브젝트여부/동일 권한여부/동일 옵티마이져 여부)
커서 캐싱
: 커서 캐싱을 디폴트(50)과 0으로 설정 후, dbms_sql 캐시지를 이용한 명시작 parse 와 execute call 수행
fori in 1..1000 loop
m_cursor := dbms_sql.open_cursor;
dbms_sql.parse(
m_cursor,
'select n1 from t1 where id = :n',
dbms_sql.native
);
dbms_sql.define_column(m_cursor,1,m_n);
dbms_sql.bind_variable(m_cursor, ':n', i);
m_rows_processed := dbms_sql.execute(m_cursor);
ifdbms_sql.fetch_rows(m_cursor) > 0 then
dbms_sql.column_value(m_cursor, 1, m_n);
end if;
dbms_sql.close_cursor(m_cursor);
end loop;
- Parse count(hard) 수치(=최적화 횟수)는 작다 ==> 루프 내 문장 재사용
- 세션 캐시에 따른 커서에 액세스 방법 차이가, 경합 차이 발생 시킴 ( 래치 gets 수치 차이 유발 )
세션 커서 캐시 : SQL 자주 수행 = 문장 커서에 KGL lock 설정, 세션 메모리 내에 state object 를 생성 후, 해당 커서와 연결
라이브러리 검색 없이 문장 사용
커서 캐싱 동작 방식
- 첫 번째 실행 시 최적화 수행
- (첫 수행 세션과 다른 세션도 가능함)두 번째 실행 시 인증 수행 ( cursor authentication = child cursor 비교작업 )
- 세 번째 실행이 완료된 이후에 캐싱
- 이후부터 캐싱된 정보 사용
세션 커서 캐시에 존재한다는 것은 parse call 시에(문장 execute 시에) 어떠한 Parsing (최적화)도 수행 하지 않는다는 것 의미
커서 홀딩
문장을 자주 사용한다면, 커서 변수 선언, 원하는 만큼 오랫동안 커서를 open 하는것이 바람직
m_cursor := dbms_sql.open_cursor;
dbms_sql.parse(
m_cursor,
'select n1 from t1 where id = :n',
dbms_sql.native
);
dbms_sql.define_column(m_cursor,1,m_n);
fori in 1..1000 loop
dbms_sql.bind_variable(m_cursor, ':n', i);
m_rows_processed := dbms_sql.execute(m_cursor);
ifdbms_sql.fetch_rows(m_cursor) > 0 then
dbms_sql.column_value(m_cursor, 1, m_n);
end if;
end loop;
dbms_sql.close_cursor(m_cursor);
- 래치 획득 수치가 추백번 정도 ( VS 이전 수천번 )
execute call 시 파싱과 최적화 발생 할 경우
: PL/SQL 최적화로 인한 홀딩(Holding) 커서의 부작용
- 홀딩 커서는 내부적으로 라이브러리 캐시 내의 자식 커서와 부모 커서와 연결되어 있다.
- 라이브러리 캐시 메모리 필요, 자식 커서의 대부분을 메모리에서 제고함(세션이 커서 홀딩하여도 )
- 이 시점에 문장을 재수행 하면, parse count(total) = sql 수행 횟수 통계 수치는 증가하지 않음에도 불구하고 Miss in library cache during exeucte 가 기록되고,
- parse count(hard)=최적화 통계가 증가한다.
결과적으로 parse count(total) < parse count(hard )