I/O 개요
- 어플리케이션 레이어 : select/insert/update/delete/truncate...
- 오라클 메모리 레이어 : Buffer cache | PGA
- 오라클 세그먼트 레이어 : Datafile, tempfile, Tablespace, Segment
- OS/디바이스 레이어 : Asynch I/O, Direct I/O, Raw Device, RAID, ...
- I/O 성능문제의 원인을 파악하는 것과 해결책을 찾는 과정은 항상 1->2->3->4의 순서를 따라야 한다.
어플리케이션 레이어(Application Layer)
- 어플리케이션을 효과적으로 구현하여, 불필요한 I/O를 최소화 해야 한다.
- I/O를 효율적으로 처리하는 다양한 기법들을 제공하며, Parallel Query, Parallel DML, Nologging, Direct Load,
Direct Read, Analytical Function등을 잘 이용하여 효과적으로 작업을 처리 해야 한다. - 데이터의 성격에 따라 클러스터(Cluster), IOT, 파티셔닝(Partitioning), 비트맵 인덱스(Bitmap Index)등의 기능을
적절히 사용해서 I/O를 효과적으로 사용하는 것 또한 어플리케이션의 몫이다.
오라클 메모리 레이어(Oracle Memory Layer)
- 버퍼 캐시는 오라클 I/O 관리의 핵심이다. 자주 사용하는 블록들을 메모리에 캐시 함으로써 물리적인 I/O를 줄일 수 있다.
- 오라클이 제공하는 Buffer Cache 기능은 다음과 같은 것들이 있다.
- Touch Count 기반의 효율적인 LRU 알고리즘을 제공한다.
- Buffer Pinning 기법을 통해 불필요한 래치 경합을 줄이고, 현재의 읽기 작업에 사용될 확률이 높은 블록들을 메모리에서 밀려나지 않게끔 한다.
- 다중 버퍼 풀(Multiple Buffer Pool) 기능을 이용하면 휘발성 블륵과 메모리 상주 블록을 구분해서 효과적으로 관리 할 수 있다.
시스템에서 보편적으로 자주 사용되는 객체들은 Default 버퍼를 사용한다. 비교적 주기적으로 사용되는 작은 크기의 객체들은
Keep 버퍼에 상주시키는 것이 좋다. 반대로 아주 적은 빈도로 사용되는 큰 크기의 객체들은 Recycle 버퍼를 사용함으로써 중요한 메모리 영역을
낭비하는 일을 방지할 수 있다. - 오라클 9i 부터는 블록 크기를 2K ~ 32K까지 사용 가능하다. 객체의 속성을 고려하여 큰 사이즈의 블록을 사용하는 것이 유리한 경우
(가령 로우의 크기가 크고 풀 테이블 스캔으로 데이터를 읽는 경우가 많은 경우)에는 큰 크기의 블록을 사용함으로써 성능 개선 효과를 얻을 수 있다. - 메모리에 올릴 필요가 없는 대용량의 데이터를 처리할 때는 버퍼 캐시를 우회하는 방법을 사용할 수 있다. (Direct Path I/O)
Direct Path I/O를 사용하면 SGA 영역을 거치지 않기 때문에 메모리 공유를 위한 동기화 매커니즘이 불필요하고 그만큼 성능이 개선된다.
다중 버펄 풀 Keep, Default, Recycle 버퍼의 기본적인 내용을 정리하면 다음과 같다.
- Default 버퍼는 자주 사용되는 객체들을 위해 사용한다.
- Keep 버퍼는 "비교적" 자주 사용되는 객체들을 위해 사용한다. 매우 자주 사용되는 객체들은
Default 버퍼의 핫(Hot) 영역에 상주할 가능성이 크기 때문에 굳이 Keep 버퍼에 상주시킬 필요가 없다.
하지만 사용빈도가 비교적 낮은 객체들의 경우에는 Default 버퍼의 콜드(Cold)영역에 있다가 버퍼
캐시에서 밀려날 확률이 높기 대문에 Keep 버퍼에 상주시키는 것이 바람직 하다. - 셋째, Recycle 버퍼는 사용 빈도가 낮은 객체들에 대해 사용한다
- Keep 버퍼와 Recycle 버퍼는 기본적으로 핫 영역(사용빈도가 높은 블록들이 머무르는 영역)과 콜드 영역
(사용빈도가 낮은 블록들이 머무르는 영역)의 구분이 없다. 정확하게 말하면 핫 영역을 가지지 않는다.
- Keep 버퍼의 경우 FTS 방식으로 읽히는 블록들은 기본적으로 LRU 리스트의 끝에 위치시키게 된다.
하지만 Keep 버퍼의 경우네는 FTS 방식으로 읽히는 것을 전제로 하기 때문에 FTS 방식으로 읽힌 블록이라고
하더라도 LRU의 제일 앞에 위치한다.
- 오라클 10G 이전 버전에서는 FTS 방식으로 읽힌 블록에 대해서는 Touch Count를 읽는 즉시 증가시키지 않았다.
이로 인해 FTS 방식으로 매우 자주 읽히는 테이블들이 버퍼 캐시에서 밀려나가는 현상이 생길 수 있다.
따라서 이런 형태의 테이블에 대해서는 가급적이면 Keep 버퍼를 사용하는 것이 바람직하다.
- 특정 객체를 Keep 버퍼에 완전히 상주시키기 위해서는 CR 블록이 차지하는 크기까지 고려해야 한다.
따라서 Keep 버퍼의 크기는 Keep 버퍼에 담을 객체들의 전체 크기보다 크게 잡는것이 바람직 하다.
오라클 세그먼트 레이어(Oracle Segment Layer)
- Temporary Tablespace를 사용할 경우, 기본적으로 데이터 파일이 아닌 임시파일(Temp File)에 데이터를 저장한다.
- 오라클 7.3 이전 버전에서는 정렬 작업을 위해 Permanent Tablespace를 사용해야 했는데 이 경우 과도한 익스텐트의
할당과 해제로 인해 많은 성능문제가 야기되며, 특히 ST락 경합으로 인한 성능 저하 현상이 생기는 경우가 많았다. - 오라클 8i부터 사용가능한 Temporary Tablespace와 Tempfile 기능을 사용하면 ST락 경합은 더이상 문제가 되지 않는다.
- 오라클 8i부터 제공되는 LMT(Locally Managed Tablespace)와 오라클 9i부터 제공되는 ASSM(Automatic Segment Space
Management)을 사용하면 익스텐트 및 세그먼트 공간의 부적절한 관리에서 오는 성능문제를 대부분 해결 할 수 있다. - 대용량의 테이블은 파티션(Partition)을 이용하면 관리적인 측변에서 뿐만 아니라, 대량의 데이터를 처리하는 경우
원하는 범위만을 스캔하는 것이 가능하므로 필요한 I/O 범위를 줄이는 효과가 있다.
OS/디바이스 레이어(Device Layer)
- 오라클은 가능하면 비동기 I/O(Asynchronous IO)를 사용할 것을 권장한다. 비동기 I/O는 읽기 작업 뿐만 아니라 특히
DBWR이나 LGWR등 쓰기 작업을 수행하는 프로세스가 비동기적으로 작업을 처리할 수 있도록 해줌으로써 I/O 작업의 속도를
전반적으로 개선시켜준다. - 많은 OS들에서 진저한 비동기 I/O는 Raw Device에서만 사용한 것으로 알려져 있다. 비동기 I/O를 사용하는 것이 불가능하다면 OS
차원에서 Direct I/O를 사용하는 것이 바람직하다. - Direct I/O를 사용하는 경우 OS의 버퍼 캐시를 우회함으로써 불필요한 I/O작업을 최소화 한다. DBWR 프로세스를 복수개로 사용하는 것 또한
방법이 될 수 있다.
- Control File의 개수나 리두로그 파일의 개수가 불필요하게 많다면 복구가 가능한 최소한만큼만 유지하는 것도 도움이 된다.
- Direct I/O를 사용할 경우 OS의 버퍼캐시를 경유하지 않으므로 그 작동 방식이 로디바이스와 거의 동일하기 때문에 Direct I/O
를 사용하는 경우에는 로디바이스를 사용할 필요가 없다는 견해가 많지만, 로디바이스가 I/O성능개선의 중요한 방법중에 하나이다.
Direct path I/O
- 오라클 I/O는 기본적으로 SGA를 경유한다. 하지만 특수한 상황에서는 SGA를 우회해서 PGA에 데이터를 올린다.
데이터를 공유할 필요가 없을 때는 버퍼캐시에 데이터를 적재하는 과정에서 발생하는 오버헤드를 피함으로써 성능을
개선하는 것이 가능하다. - 버퍼 캐시내의 변경된 블록을 데이터파일에 기록하는 것은 DBWR 고유의 작업이다. 반면 버퍼 캐시를 우회하는 쓰기
작업은 개별 프로세스가 직접 수행하게 된다. 이처럼 버퍼 캐시를 우회하는 I/O 작업을 direct path I/O라고 부른다. - Direct Path I/O를 사용하는 경우
- 정렬작업을 위해 정렬 세그먼트(Sort Segment)를 읽고 쓰는 경우. direct path read temp, direct path write temp 이벤트를 대기
- Parallel Query를 위해 데이터파일을 읽는 경우. direct path read 이벤트를 대기한다.
- PDML이나 CTAS를 위해 데이터 파일을 쓰는 경우. direct path write 이벤트를 대기한다.
- NOCACHE 속성으로 생성된 LOB 세그먼트를 읽고 쓰는 경우. direct path read(lob), direct path write(lob)이벤트를 대기한다.
- I/O 시스템이 데이터를 읽어서 오라클에 반환하는 속도보다 훨씬 빠른 속도로 버퍼를 요구할 때.
이 경우 오라클 성능개선을 위해 readahead I/O(이후에 읽을 것으로 판단되는 데이터를 미리 한꺼번에 읽는 I/O 작업을 말함)
를 이용한다. 이 경우 direct path read 이벤트를 대기한다.
- Direct Path I/O와 관련된 통게 값에 대한 정리
- physical reads : 디스크에서 읽은 블록 수. Direct path I/O 여부와 무관하게 물리적인 읽기 작업이 발생할 경우에는 항상 증가한다.
- Physicla reads direct : Direct path I/O를 통해 읽은 블록 수. LOB 데이터에 대한 direct path I/O는 포함하지 않는다.
- physical reads direct(lob) : LOB 데이터를 direct path I/O를 통해 읽는 블록 수
- physical writes : 디스크에 기록한 블록 수. Direct path I/O 여부와 무관하게 물리적인 쓰기 작업이 발생할 경우에는 항상 증가한다.
- physical writes direct : Direct path I/O를 통해 기록한 블록 수. LOB 데이터에 대한 direct path I/O는 포함하지 않는다.
- physical writes direct(lob) : LOB 데이터를 direct path I/O를 통해 기록한 블록 수
- sort(disk) : 디크를 이용한 정렬 작업 회수. 디스크를 이용한 정렬 작업이 발생할 경우에는 정렬 세그먼트에 대해 direct path I/O를 사용한다.
- sort(memory) : 메모리수를 이용한 정렬 작업 회수.
Conventional Path I/O의 공식
Conventional Physical reads = physical reads(physical reads direct + physical direct(lob))