데이터 저장 구조 및 I/O 매커니즘2

운구름·2022년 5월 3일
0
post-thumbnail

Single Block I/O vs Mulit Block I/O

Single Block I/O

  • 디스크 I/O 한번에 한 블록씩 요청해서 메모리에 적재하는 방식
  • 인덱스와 테이블 블록 모두 이 방식을 사용
  • 인덱스는 소량의 데이터를 읽어서 이 방식이 효율적임.

Mulit Block I/O

  • 한번에 여러 블록을 요청해서 메모리에 적재하는 방식
  • 대상 블록과 인접한 블록들을 한꺼번에 읽어 캐시에 미리 적재하는 방식
  • 테이블 전체를 스캔(Full Scan)할때 좋은 방식 (I/O 할때 프로세스 Sleep을 줄여줌)

Mulit Block Read Count

DBMS가 Mulit Block I/O 수행하면서 한번에 가져올수 있는 블록의 총 갯수이다. (책에서는 손수레로 표현)

  • 오라클의 블록 단위 : 8kb
  • 최대로 설정할 수 있는 Mulit Block Read Count : 128
  • 8kb * 128 = 1024kb = 1Mb
  • 즉, Mulit Block I/O 수행하며 가져올 수 있는 최대 크기 : 1Mb

Mulit Block I/O 는 익스텐트를 벗어나지 못한다.

예시

  • 1개의 익스텐트의 블록 수 : 20개로 가정
  • Mulit Block Read Count : 8 이라고 가정
  • 한개의 익스텐트 처음부터 읽었을때 읽는 블록
    - 1번째 Mulit Block I/O : 1 ~ 8
    • 2번째 Mulit Block I/O : 9 ~ 16
    • 3번째 Mulit Block I/O는? : 16 ~ 20 (24가 아님)

즉, MulitBlock I/O는 익스텐트 경계를 넘을 수 없다.

Single Block I/O와 Mulit Block I/O는 섞어 쓴다.

익스텐트 안의 블록을 전체 읽어야 하는데, 만약 일부가 버퍼캐시에 있다면?
버퍼캐시에서 읽을 블록을 확인하고, 듬성듬성 읽게 되는 블록이 있다면 Single Block I/O를 사용하는게 적절하다.

  • 아래는 익스텐트이다. 아래의 1~10까지의 번호는 블록의 번호이다.
  • 괄호친 블록의 번호는 버퍼캐시에 있다.
  • M : MulitBlock I/O
  • B : 버퍼캐시
  • S : Single Block I/O
1234(5)6(7)8910
MMMMBSBMMM
  • 1 ~ 4번까지: Mulit Block I/O
  • 5번: 버퍼캐시로 메모리 I/O
  • 6번: Single Block I/O
  • 7번: 버퍼캐시로 메모리 I/O
  • 8~10번: Mulit Block I/O

Table Full Scan vs Index Range Scan

Table Full Scan

  • 테이블 전체를 스캔해서 읽는 방식
  • 다량의 데이터를 읽을 때 좋은 방식
  • 시퀀셜 액세스와 Mulit Block I/O 방식을 이용하여 디스크 블록을 읽는다.

Index Range Scan

  • 인덱스를 이용해서 읽는 방식
  • 소량의 특정 데이터를 검색할 때 좋은 방식
  • 인덱스에서 일정량을 스캔해서 얻은 ROWID로 테이블 레코드를 찾아가는 방식
  • 랜덤 액세스와 Single Block I/O 방식으로 디스크 블록을 읽는다.

ROWID는 테이블 레코드가 디스크상에 어디에 저장 되어있는지 가리키는 위치정보

Table Full Scan이 오히려 Index Range Scan보다 좋은 경우가 있을 수 있다.
한번에 많은 데이터를 처리하는 집계용 SQL과 배치 프로그램은 Table Full Scan이 좋을 수 있음.
조인을 포함한 SQL이면 '해시조인' 선택해주면 된다.

왜 인덱스가 느릴까?

  • Single Block I/O와 Mulit Block I/O
  • Index Range Scan와 Table Full Scan

많은 데이터를 읽으려고 할때 인덱스를 이용하면 Table Full Scan이 유리함. => 읽으려는 데이터 양의 차이.

많은 양의 데이터를 Index Scan하면 Single Block I/O를 엄청 많이 하기 때문에 I/O가 많아지는 것은 속도가 느려지는 것이다.

캐시 탐색 메커니즘

Direct Path I/O를 제외한 모든 블록 I/O는 메모리 버퍼캐시를 경유함.

버퍼캐시 탐색과정

아래 오퍼레이션은 모두 버퍼캐시 탐색과정을 거침

  • 인덱스 루트 블록을 읽을 때
  • 인덱스 루트 블록에서 얻은 주소 정보로 브랜치 블록을 읽을 때
  • 인덱스 브랜치 블록에서 얻은 주소 정보로 리프 블록을 읽을 때
  • 인덱스 리프 블록에서 얻은 주소정보로 테이블 블록을 읽을 때
  • 테이블 블록을 Full Scan 할 때

버퍼캐시에서 블록을 찾을 때, 해시 알고리즘으로 버퍼 헤더를 찾음. 헤더에서 얻은 포인터로 버퍼 블록을 액세스 함.

해시 구조의 특징 (Hash를 알면 패스)

  • 같은 입력값은 항상 동일한 해시 체인에 연결됨.
  • 다른 입력값이 동일한 해시 체인에 연결될 수 있음.
  • 해시 체인 내에는 정렬이 보장되지 않음.

메모리 공유 자원에 대한 액세스 직렬화

  • 버퍼캐시는 SGA라서 버퍼캐시에 캐싱된 버퍼블록은 공유 자원임.
  • 버퍼캐시는 누구나 접근 가능
  • 버퍼캐시 내 버퍼블록을 2개 이상 프로세스가 동시 접근하려고 하면 블록 정합성에 문제가 생김.
  • 직렬화(serialization) 매커니즘을 사용하여 순차 접근하도록 구현
  • 직렬화가 가능하도록 지원하는 매커니즘이 래치(Latch)이다.

캐시버퍼 체인 래치

  • 해시체인을 스캔하는 동안 다른 프로세스가 체인 구조를 변경하는걸 막기 위해 체인래치가 존재함.
  • 체인에 접근하기 위해 프로세스가 래치 Key를 획득해야만 해시 체인에 접근할 수 있다.
  • 캐시 히트율을 올려도 이 체인 래치의 경합 때문에 생각보다 빠르지 않을 수 있다.

버퍼캐시에 작동하는 래치

  • 캐시버퍼 체인 래치
  • 캐시버퍼 LRU 체인 래치

버퍼 Lock

  • 버퍼 블록에 존재하는 직렬화 매커니즘이다.
  • 래치 해제한 상태로 버퍼블록 사용 도중, 후행 프로세스가 같은 블록에 접근할 경우 정합성의 문제가 생김. 이를 방지하기 위한 매커니즘이다.
  • 캐시버퍼 체인래치를 해제하기 전에 버퍼 헤더에 Lock을 설정함으로써 버퍼 블록 자체에 대한 직렬화 문제 해결

직렬화 매커니즘에 의한 캐시 경합을 줄이려면 SQL 튜님을 통해서 쿼리의 "논리적 I/O" 자체를 줄여야 한다.

profile
뭉실뭉실 코더 운구름

0개의 댓글