본문 바로가기
스터디/오라클 성능고도화 원리와 해법1

06.I/O 효율화 원리 - 03. Single Block vs. Multiblock I/O

by 취미툰 2020. 2. 11.
반응형

I/O Call 수행원리에 대해서 살펴보겠습니다. Call통계를 보면 버퍼캐시에서 query + current 의 개수로 블록을 읽고, disk 항목으로 디스크에서 읽었다는 것을 확인할 수 있습니다. 만약 디스크에서 읽은 블록 개수가 64개라고 해서 I/O Call까지 64번 발생했음을 의미하지는 않습니다. 64번일 수도 있고, 그보다 작을 수도 있습니다.
읽고자 하는 블록을 버퍼 캐시에서 찾지 못했을 때, I/O 를 통해 데이터파일로부터 버퍼 캐시에 적재하는 방식에는 두가지 방식이 있습니다.
Single Block I/O는 말 그대로 한번의 I/O Call에 하나의 데이터 블록만 읽어 메모리에 적재하는 것을 말합니다. 인덱스를 통해 테이블을 액세스 할 때는, 기본적으로 인덱스와 테이블 블록 모두 이 방식을 사용합니다.
Multi Block I/O는 I/O Call 시점에 인접한 블록들을 같이 읽어 메모리에 적재하는 것을 말합니다. 오라클 블록 상이즈가 얼마건 간에 OS단에서는 보통 1MB(1,024KB)단위로 I/O를 수행합니다. 한번 I/O할때 1MB 크기의 그릇을 사용하는 것이므로 테이블 full scan처럼 물리적으로 저장된 순서에 따라 읽을 때는 그릇이 허용하는 범위 내에서 인접한 블록들을 같이 읽는 것이 유리합니다. ‘인접한 블록’이란 한 익스텐트 내에 속한 블록들을 말합니다. 달리 말하면 MultiBlock I/O방식으로 읽더라도 익스텐트 범위를 넘지 못한다는 뜻이기도 합니다.
Multiblock I/O단위는 db_file_multiblock_read_count 파라미터에 의해 결정됩니다. 파라미터가 16이면 한번에 16개의 블록을 최대 버퍼 캐시에 저장합니다. 대게 OS 단위에서 I/O 단위가 1MB이므로 db_block_size가 8,192일 때는 최대 설정할 수 있는 값은 128이 됩니다. 이 파라미터를 128이상으로 설정하더라도 OS가 허용하는 I/O단위가 1MB면 1MB만 읽습니다.

인덱스 블록간 논리적 순서는 물리적으로 데이터파일에 저장된 순서와 다릅니다. 인덱스 블록간 논리적 순서란, 인덱스 리프 블록끼리 이중 연결 리스트 구조로 연결된 순서를 말합니다. 물리적으로 한 익스텐트에 속한 블록들을 I/O Call 발생 시점에 같이 적재해 올렸는데, 그 블록들이 논리적 순서로는 한참 뒤쪽에 위치할 수 있습니다. 그러면 그 블록들은 실제 사용되지 못한 채 버퍼 상에서 밀려나는 일이 생길 수 있습니다. 하나의 블록을 캐싱하려면 다른 블록을 밀어내야 하는데, 이런 현상이 자주 발생한다면 버퍼 캐시 효율만 떨어뜨리게 됩니다. 따라서 인덱스 스캔 시에는 SIngle Block I/O방식으로 읽는 것이 효율적입니다.
Index Range Scan 뿐 아니라 Index Full Scan시에도 논리적인 순서에 따라 Single Block I/O방식으로 읽습니다. 인덱스의 논리적 순서를 무시하고 물리적인 순서에 따라 읽는 스캔 방식이 있는데, 이를 ‘Index Fast Full Scan’이라고 합니다. 이때는 Table Full Scan과 마찬가지로 Multiblock I/O방식을 사용하며, 한 번에 읽을 수 있는 최대 블록 수도 똑같이 db_file_multiblock_read_count파라미터에 의해 결정됩니다.

서버프로세스는 디스크에서 블록을 읽어야 하는 시점마다 I/O서브시스템에 I/O요청을 하고 대기 상태에 빠지는데, 이때 발생하는 대표적인 대기 이벤트가 두개 있습니다.
db file sequential read : Single Block I/O방식으로 I/O요청할때 발생
db file scattered read : Multiblock I/O 방식으로 I/O요청할때 발생
대량의 데이터를 Multiblock I/O방식으로 읽을 때 Single Block I/O보다 성능상 유리한 것은 I/O Call 발생횟수를 그만큼 줄여주기 때문입니다.
10g부터는 Index Range Scan 또는 Index Full Scan일때도 Multiblock I/O방식으로 읽는 경우가 있는데, 테이블 액세스 없이 인덱스만 읽고 처리할 때가 그렇습니다.인덱스를 스캔하면서 테이블을 Randdom액세스할 때는 9i이전 방식과 동일하게 테이블과 인덱스 모두 Single block I/O방식으로 읽습니다.
Single block I/O방식으로 읽은 블록들은 LRU리스트 상 MRU(end)쪽으로 연결되므로 한번 적재되면 버퍼 캐시에 비교적 오래 머뭅니다. 하지만 Multiblock I/O방식으로 읽은 블록들은 LRU리스트에서 LRU(end)쪽에 연결되므로 적재되고 얼마 지나지 않아 버퍼 캐시에서 밀려납니다.
따라서 대량의 Full Scan을 했다고 해서 사용빈도가 높은 블록들이 버퍼 캐시에서 모두 밀려날 것을 우려하지 않아도 됩니다.

반응형

댓글