본문
- 빠른 데이터 입출력을 위해 SGA 공유 메모리를 이용한다고 설명했는데,
좀더 구체적으로 말하면 사용자가 입력한 데이터를 데이터 파일에 저장하고
이를 다시 읽는 과정에서 거쳐 가는 캐시 영역은 SGA 구성요소 중 하나인 DB 버퍼 캐시이다.
(1) 블록 단위 I/O
- 오라클에서 I/O는 블록(Block) 단위로 이루어짐
- 액세스 할 때 뿐만 아니라 데이터 블록을 DB 버퍼 캐시로 적재하거나 변경된 블록을 다시 데이터 파일로 저장할 때도
블록 단위로 처리
- 데이터 파일에서 버퍼 캐시로 블록을 적재할 때,
Single Block Read : 인덱스를 경유한 테이블 액세스시에 한번에 한 블록씩
Multi Block Read : Full Scan 시에는 성능 향상을 위해 한번에 여러개 블록을 읽어들인다.
- DBWR : 버퍼 캐시로부터 변경된 블록(Dirty Block)을 주기적으로 데이터파일에 기록하는 작업을 수행(블록 단위)
- 블록 단위로 읽는다는 의미는, 하나의 레코드에서 하나의 컬럼만 읽고자 하더라도 레코드가 속한 블록 전체를 읽게 됨을 의미
- SQL 성능을 좌우하는 가장 중요한 성능지표는 액세스하는 블록의 개수이며 옵티마이저의 판단에도 영향을 미친다.
ex) 옵티마이저가 인덱스를 이용해 테이블을 액세스 할지 Full Table Scan을 할지를 결정하는데 있어 가장 중요한
판단 기준은 읽어야할 레코드 수가 아니라 블록 개수
(2) 버퍼 캐시 구조
- DB 버퍼 캐시는 해시 테이블 구조로 관리
- 데이터 블록 주소(DBA, Data Block Address) : DB 버퍼 캐시 내에서 데이터 블록을 해싱하기 위해 사용되는 키 값
- 해시 함수에 DBA를 입력해 리턴받은 해시 값이 같은 블록들을 해시 버킷에 연결 리스트(Linked List) 구조로 연결
- 각각의 연결 리스트를 해시 체인(Hash Chain)이라고 한다.
- 버퍼 헤더(Buffer Header)만 체인에 연결되며 실제 데이터 값이 필요해지면 버퍼 헤더에 있는 포인터를 이용해
다시 버퍼 블록을 찾아가는 구조.
- Hash table → Hash bucket → buffer header chain → buffer header → buffer body → block header → block body
(3) 캐시 버퍼 체인
- 각 해시 체인은 래치(Latch)에 의해 보호된다.
- 해시 체인은 SGA 내에 존재, 여러 프로세스에 의한 동시 액세스가 일어날 가능성이 크다.
- 래치 : 같은 리소스에 대한 액세스를 직렬화(Serialization) 하기 위한 Lock 메커니즘
- cache Buffers Chains Latch : 두개 이상의 프로세스가 같은 해시 체인으로 진입해 새로운 버퍼 블록을
연결/해제하는 작업이 동시에 작업할 때 발생하는 문제를 방지하기 위한 래치
- 래치의 종류
SQL> Select count(*) from v$latchname;
버 전 |
9i |
10g |
11g |
개 수 |
241 |
394 |
496 |
※ 같은 버전이더라도 Release에 따라 개수에 차이가 있다.
- 하나의 cache buffers chains 래치가 여러개 해시 체인을 동시에 관리한다.
- 하나의 해시 버킷과 해시 체인은 1:1 관계
- 해시 버킷과 래치 개수는 _db_block_hash_buckets과 _db_block_hash_latches 파라미터 값을 통해 확인
- 래치는 데이터 자체를 보호하는 것이 아니라 SGA에 공유돼 있는 자료 구조를 보호하는 것
- cahce buffers chains 래치는 버퍼 캐시에 연결된 체인 구조를 보호함
- 해시 체인을 스캔하거나 거기에 블록을 추가, 제거할 때 래치가 요구된다.
- 9i부터는 읽기 전용 작업일 경우에 cache buffers cahins 래치를 Shared 모드로 획득이 가능함.
(4) 캐시 버퍼 LRU 체인
- 버퍼 헤더는 해시 체인 뿐 아니라 LRU 체인에 의해서도 연결되어 있다.
- 버퍼 캐시가 사용 빈도가 높은 데이터 블록들 위주로 구성될 수 있도록 LRU(Least Recently Used) 알고리즘을 사용해
관리된다.
- 모든 버퍼 블록 헤더를 LRU 체인에 연결해 사용빈도 순으로 위치를 옮겨가다가, Free 버퍼가 필요해질 때마다
액세스 빈도가 낮은 데이터 블록들을 우선하여 밀어냄으로써
자주 액세스되는 블록들이 캐시에 더 오래 남아 있도록 관리한다. (그림 참조)
- LRU 리스트에는 내부적으로 두 개의 리스트를 갖는다.
┌ Dirty 리스트 : 캐시 내에는 변경됐지만, 아직 디스크에 기록되지 않은 Dirty 버퍼 블록들을 관리하며
│ 'LRUW 리스트'라고도 한다.
└ LRU 리스트 : 아직 Dirty 리스트로 옮겨지지 않은 나머지 버퍼 블록들을 관리한다.
- 모든 버퍼들은 둘 중 하나에 반드시 속하지만 읽기 / 쓰기 작업을 위해 액세스되는 동안에는 리스트에서 잠시 풀려나왔다가
다시 원래 리스트로 연결되거나, 최초 변경이 발생하였을 때는 Dirty 리스트로 옮겨진다.
- cache buffers lru chain Latch : LRU 리스트를 보호하기 위해서 사용하는 래치
- LRU 리스트의 버퍼 상태
1) Free 버퍼 : 인스턴스 기동 후 아직 데이터가 읽히지 않아 비어있는 상태(Clean 버퍼)이거나 언제든지 덮어 써도
무방한 버퍼 블록
2) Dirty 버퍼 : 버퍼에 캐시된 이후 변경이 발생했지만, 아직 디스크에 기록되지 않아 데이터 파일 블록과 동기화가
필요한 버퍼 블록
3) Pinned 버퍼 : 읽기 또는 쓰기 작업을 위해 현재 액세스되고 있는 버퍼 블록
조시형,『오라클 성능 고도화 원리와 해법Ⅰ』, (주)비투엔컨설팅, 2009, pp.23-39
'Oracle > Oracle_성능고도화' 카테고리의 다른 글
[Chapter 01] 오라클 아키텍처 - 03 버퍼 Lock (0) | 2014.09.22 |
---|---|
[Chapter 01] 오라클 아키텍처 - 01 기본 아키텍처 (0) | 2014.09.22 |