=================================================================================
1. 공유커서 (Shared Cursor) : Library Cache에 공유돼 있는 Shared SQL Area
2. 세션커서 (Session Cursor) : Private SQL Area에 저장된 Cursor
3. 애플리케이션 커서 (Application cursor) : 세션Cursor를 카리키는 핸들
=================================================================================
1. 공유커서
◇ JAVA, VB, Pro*C, PL/SQL 등에서 SQL을 수행하면 Server Process는 해당 SQL이 Library Cache에 공유돼 있는지를
먼저 확인한다.
◇ Library Cache에 공유돼 있는 Shared SQL Area를 'Cursor'라 한다.
2. 세션커서
◇ Library Cache에 공유돼 있는 Cursor를 실행할 떄, 우선 PGA영역에 메모리를 할당.
이를 'Private SQL Area'라 한다.
◇ Private SQL Area
- Persistent Area : 바인드 변수 등을 저장하며 실행 종료 후 Cursor가 닫힐 떄 해제 된다
- Runtime Area : select문은 모든 record를 Fetch완료하거나 실행을 취소할 때 해제되지만,
insert, update, delete는 실행이 종료됨과 동시에 해제 된다.
◇ Shared SQL Area를 읽어서 실행하는데 필요한 정보들을 Private SQL Area에 담고,
공유 Cursor를 가리키는 포인터를 유지하며,
Cursor상태(open, bound, execute, close 등) 정보도 관리한다.
⇒ 이러한 준비과정을 'Cursor를 오픈한다'라 표현한다.
◇ Cursor : PGA에 저장된 Cursor 정보(파싱된 SQL문, 문장을 수행하는데 필요한 기타 정보)
3. 애플리케이션 커서
◇ PGA에 있는 Cursor를 핸들링하려면 JAVA, VB, Pro*C, PL/SQL같은 클라이어트 애플리케이션에도
리소스를 할당해야 하는데, 이 또한 'Cursor'라는 용어를 사용한다.
▶ 커서공유
◇ "Cursor를 공유한다" 표현에서 Cursor는 Library Cache으 공유 Cursor를 일컫는다.
Session Cursor, Application Cursor는 다른 Process와 공유할 수 없다.
◇ V$SQL
- 실제 공유된 Cursor가 어떻게 반복·재사용되는지 확인.
- Child Cursor 정보를 보여준다 (cf : v$sqlarea는 Parent Cursor 정보를 보여준다).
┌ parse_calls : Library Cache에서 SQL Cursor를 찾으려는 요청 횟수
├ loads : 하드파싱을 거친 SQL 실행계획을 Library Cache에 적재한 횟수
├ executions : SQL을 수행한 횟수
└ invalidations : Cursor가 무효화된 횟수. Cursor가 참조하고 있는 오브젝트에 중요한 변화가 일어났음을 의미
→Cursor가 무효화의 예 : Cursor가 참조하고 있던 오브젝트에 column이 삭제, 추가 되거나,
새로운 index가 만들어지거나, 오브젝트 통계를 새로 수집하는 등의 DDL문이 수행되는 경우
◇ Cursor가 공유되려면 Cursor를 식별하는 키 값이 같아야 한다.
Library Cache에서 Cursor를 식별하기 위해 사용하는 key 값은 'SQL문장 그 자체' 문자열이 이름 역할을 한다.
◇ V$SQL을 조회해 보면, sql_id 라는 별도의 식별자 column(10g부터)
- sql_id와 sql_full text는 1:1로 대응되므로 SQL문 중간에 작은 공백문자 하나만 추가하더라도
서로 다른 SQL문장으로 인식해 새로운 sql_id를 발급 받게 된다.
⇒ 즉, Cursor가 공유되지 않는다.
▶ Child Cursor를 공유하지 못하는 경우
◇ Object LCO (stored Object)
- 생성될 때부터 유일하게 식별 가능한 이름이 부여되므로 Child Object를 사용할 필요가 없다.
◇ 실행가능 LCO (Transient Object) = SQL Cursor
- 이름을 따로 지정하지 않고 문장을 구성하는 전체 문자열 그대로가 LCO식별하는 이름.
⇒ 그래서, 전체 문자열은 같지만 다른 방식으로 실행해야하거나
파싱 시키마에 따라 다른 Object를 참조하는 상황에서는 Child Cursor가 필요
- SQL마다 하나의 Parent Cursor를 가지며, 적어도 한개의 Child Cursor를 갖는다.
★ 하나의 SQL문장이 여러개 Child Cursor를 갖는 이유-------------------------------------------------------
① SQL에서 참조하는 Object명이 같지만 실행한 사용자에 따라 다른 Object를 가리킬 때
② 참조 Object가 변경돼 Cursor가 무효화되면 이후 그 Cursor를 처음 사용하려는 세션에 의해
다시 하드파싱이 되야하는데, 특정 세션이 아직 기존 Cursor를 사용 중(Pin)일 때
③ 옵티마이저 모드를 비롯해 옵티마이저 관련 파라미터가 다를 때
④ 입력된 바인드 값의 길이가 크게 다를 때
⑤ NLS 파라미터를 다르게 설정했을 때
⑥ SQL 트레이스를 활성화 했을 떄
---------------------------------------------------------------------------------------------------------
이는 새로운 Cursor가 왜 기존 Child Cursor와 공유되지 못했는지에 대한 이유가 되기도 한다(v$sql_shared_cursor).
▶ Parent Cursor를 공유하지 못하는 경우
◇ 의미적으로 같고 실행환경이 같은데도 Cursor를 공유하지 못해서 Parent Cursor 자체가 여러개 생성되는 경우
① 공백 문자 또는 줄바꿈
② 대소문자 구분
③ Table owner 명시
④ 주석(comment)
⑤ 옵티마이저 힌트 사용 (의도적인 것)
⑥ 조건절 비교 값 (Library Cache와 직접 관련이 큼)
⇒ 조건절에 바인드 변수를 사용하지 않고 서로 다른 Literal 값으로 문자열을 대체하는 경우!
'용어,개념' 카테고리의 다른 글
Dynamic Performance Views (0) | 2010.09.02 |
---|---|
Hidden Parameters (0) | 2010.09.02 |
ORACLE_BASE와 ORACLE_HOME는 무엇인고~? (0) | 2010.09.01 |
Initialization Parameter Files (0) | 2010.08.29 |
Dynamic Performance Views (0) | 2010.08.29 |