공유 풀 (Shared Pool)
- SQL수행 관련 정보, SGA관리 아키텍쳐, DB설정 정보 저장
- 정적영역
- 오라클 파라미터 설정 값, 워킹셋, 자원테이블, SGA관리 아키텍쳐 및 기타정보 저장
- 사용자 정의불가. 고정된 크기로 자동설정됨.
- 동적영역
- 라이브러리 캐시, 딕셔너리(로우) 캐시 영역으로 구성
- SHARED_POOL_SIZE 파라미터값으로 설정
- SGA 자동관리(ASMM) 기능 사용 시,
SGA_TARGET 값 이내의 범위에서 MMAN 프로세스에 의해 동적으로 사이즈 변경됨 - OS 메모리의 heap 영역으로 구성되어있음
{note}
heap영역 : 헤더와 하나이상의 메모리 익스텐트들로 구성
- 메모리 익스텐트들은 지속적으로 할당, 반납되면서 작은 조각(청크,chunk)으로 나눠진다.
이런 현상을 공유풀 공간의 단편화(fregmentation)라 한다. - 청크(chunk)는 free list 에 의해 관리된다.
- 청크 재사용률을 높이기 위해 한 번 사용된 청크는 다시 free list 에 등록되기 전까지
공유 풀 LRU 리스트에 의해 관리
{note}
- 공유 풀에 메모리 할당 과정
(신규 SQL 파싱 시 256 byte공간이 필요하다고 가정)
- 메모리 공간 할당을 위해, shared pool latch를 획득하고 free list 에서 256 byte free chunk를 찾는다.
- latch 획득 후 free list에서 256 byte의 free chunk 존재 시 해당 chunk를 익스텐트에 할당
- latch 획득하지 못하면 latch: shared pool 대기 이벤트를 발생시키며 대기
- 필요한 chunk보다 큰 사이즈의 chunk를 획득할 경우, 필요한 사이즈를 쪼갠 후 나머지는 free list에 등록된다
- free list에서 free chunk 가 없다면
- 공유 풀의 LRU 리스트에서 재사용가능한 chunk를 찾아 free list로 등록 후 메모리 할당한다.
- 없으면 ORA-4031 unable to allocate %s bytes of shared memory 에러 발생, 파싱 실패
라이브러리 캐시
- 공유 커서, 파스 트리, 실행 계획 및 테이블, 시퀀스 등 DB오브젝트 정보 저장 및 관리
- 공유 커서 : 메모리 영역에 저장되어 있는 SQL, PL/SQL 정보를 찾기위한 가상의 주소
- SQL과 관련된 정보를 저장하므로 성능 관점에서 가장 중요한 부분
- 힙 오브젝트(Heap Object)
- 공유 커서 및 DB오브젝트 정보 저장
- 최종적으로 SQL 수행에 필요한 정보를 저장
- 저장 정보 종류에 따라 0~11번 번호를 가짐
- 0번 Heap은 Heap object 에 저장된 공유 커서, DB오브젝트의 기본정보 및 1~11번 힙 메모리 주소 값 저장
- 오브젝트 핸들(Object Handle)
- Heap object관리
- 공유 커서 문장, DB오브젝트 이름, 네임스페이스 정보, 락/핀 관련 정보, 오브젝트 핸들 상태 저장하는 플래그, 0번 힙 오브젝트 저장
- 인스턴스 시작 시 생성된 오브젝트 핸들은 인스턴스 종료 시까지 라이브러리 캐시에 남아있다
- 네임스페이스 (힙 오브젝트에 저장된 데이터 종류)
- BODY/TYBD - 프로시저, 함수, 매키지, 타입 바디
- CLST- 클러스터
- CRSR 공유커서(SQL문장)
- INDX 인댁스
- TABL/TYPE- 테이블, 뷰, 시뭔스, 동의어
- TRGR- 트리거
- 해시 버킷(Hash Bucket)
- 오브젝트 핸들 관리
- 라이브버리 캐시 매니저로 공유 커서 및 DB오브젝트 이름에 해시 알고리즘 적용
- 하나의 해시 버킷은 하나 이상의 오브젝트 핸들을 관리한다
- 라이브러리 캐시 영역의 각 구조는 동시 세션 및 동시요청에 의해 정보 공유
=> 동시성 제어와 일관성 유지를 위해 락/핀 알고리즘 을 사용한다.
로우/딕셔너리 캐시
- 데이터 딕셔너리를 저장하는 영역은 Dictionary cache라 불리고, 저장 영역이 row 단위로 저장되기 때문에 Row cache라 불린다.
- SQL 파스 단계에서 라이브러리 캐시와 함께 반드시 액세스가 필요
- Row cache도 해시 버킷 구조에 의해 관리된다.
- SQL 파스 단계에서 딕셔너리 정보 획득하기 위해 참조
- Row cache에 필요한 데이터 없는 경우, 딕셔너리 테이블에 저장된 데이터를 Row cache로 복사,
- Row Cache Object (RCO) 를 생성한다.
- shared pool 내 딕셔너리 캐시가 차지하는 공간 확인
공유 커서
- Shared Cursor는 여러 사용자에 의해 공유되어 사용되는 SQL, PL/SQL문을 의미
- Cursor공유 시, 새로운 오브젝트 핸들, 힙 오브젝트 생성 과정이 생략되어 수행속도 향상 및 메모리 단편화 방지
SQL 처리단계
- 구문분석 - SQL문 해석 및 실행계획 생성
- 라이브러리 캐시 검색 -> 구문 오류 확인 -> 참조 오브젝트 확인 -> 권한 확인 -> 쿼리 변환 -> 실행 계획 생성
- 바인드 - 조건절에 사용된 바인드 변수를 주어진 상수 값으로 치환
- 실행 - 구문분석 단계에서 생성된 실행계획에 따라 SQL문 실행
- 패치 - 실행에서 추출된 결과 반환
_OPTIM_PEEK_USER_BINDS
: 처음 수행되는 바인드 변수 값을 참조하여 실행 계획을 생성할 수 있는 히든파라미터로,
Default 값이 TRUE 이며, FALSE 값일 경우 바인드 변수 값을 참조하지 않고 실행계획을 생성
10g 에서는 FALSE로 변경 후 평균적인 통계 정보를 통해 실행계획을 생성하는 것을 권장.
- 라이브러리 캐시의 부모커서, 자식커서가 모두 공유되어야 완전한 커서 공유가 가능함.
- 부모 커서 : 수행된 SQL문 저장
- 자식 커서 : 수행된 SQL문의 실행계획 저장
< 1. 부모커서, 자식커서를 모두 공유하는 경우 >
- 바인드 변수를 사용한 SQL의 경우 변수 값이 달라지더라도, 동일한 SQL로 인식하므로 부모커서, 자식커서를 모두 공유한다.
- SQL은 ASCII값으로 변환되어 인식되므로, 대소문자, 공백이 모두 동일하게 수행되어야 한다.
< 2. 부모커서는 공유, 자식 커서를 공유하지 못하는 경우 >
- 수행한 SQL은 동일하므로 부모 커서 공유
- SQL이 각 사용자가 소유한 테이블을 호출하여 각각 소유의 테이블에 대한 실행계획을 갖는 자식커서 공유
- V$SQL에서 커서 공유 여부 확인이 가능하다.
- 바인드 변수를 사용하지 않는 리터럴(Literal) SQL의 경우 커서를 공유하지 않는다
- 잦은 파싱으로 성능상 영향이 있으므로, 바인드 변수를 사용하도록 변경한다.
데이터 분포와 SQL용도에 따라 바인드 변수 사용 여부를 결정해야 한다.
- OLTP 시스템에서 사용 빈도가 높은 SQL
- 하드 파스로 인한 성능이슈가 있으므로, 바인드 변수를 사용
- 편중된 데이터를 조회하는 SQL, DW시스템과 같이 SQL사용 빈도가 높지 않은 시스템일 경우
예약 풀
- 기본 값으로 4,400 byte가 넘는 SQL은 shared pool 내 예약풀(Reserved Pool)에 저장
- 4,400 byte 이하로 단편화 되지 않으므로 ORA-4031에러 발생 빈도가 적다.
- SHARED_POOL_RESERVED_SIZE 파라미터로 설정 ( SHARED_POOL_SIZE 설정된 풀에서 메모리를 할당받음 )
- 예약 풀 기본크기는 shared pool 크기의 5% , 50%이상은 초과 불가
- SQL 사이즈 임계값은 _SHARED_POOL_RESERVED_MIN_ALLOC 값으로 변경 가능
- 예약풀 크기 확인은 V$SHARED_POOL_RESERVED 뷰 조회
- REQUEST_MISSES 값이 0이면 충분함. 해당 값이 증가 시 예약 풀 크기가 부족하므로 더 크게 변경해야 함.
대기 이벤트
- shared pool 에서 발생 가능한 대표적인 대기이벤트(wait event)
- 공유 풀의 성능 향상을 위해서는 리터럴SQL에 의한 하드파스를 없애는 것!