728x90
I/O 튜닝이 곧 SQL 튜닝이라 해도 과언이 아니다.
- I/O = 잠자는시간
- I/O가 일어나는 시간동안 프로세스는 잠을 자기 때문
- I/O가 발생하면 프로세스는 대기큐에서 잠을 잔다. 그리고 I/O가 끝나면 디스패처에 의해 다시 일한다.
시퀀셜 엑세스 vs 랜덤 엑세스
- 시퀀셜 엑세스
- 논리적, 물리적으로 연결된 순서에 따라 차례대로 블록을 읽는 방식
- 랜덤 엑세스
- 순서를 따르지 않고 레코드 하나를 읽기 위해 한 블록씩 접근하는 방식
논리적 I/O vs 물리적 I/O
- System Global Area (SGA)
- DB Buffer Cache, Redo Log Buffer, Shared Pool (Library Cache : SLQ), Data Dictionary Cache
- 여러 메모리와 사용사 세션이 공유하는 공간
- DB버퍼캐시
- 데이터 캐시라고 볼 수 있다. I/O를 통해 얻은 귀중한 데이터를 저장한다.
- 오라클에서 확인하는 방법 : show sga
- 논리적 I/O
- SQL을 처리하는 과정에서 발생한 총 블록 I/O를 말한다. 메모리 I/O가 곧 논리적 I/O이다.
- 물리적 I/O
- 실제 디스크에에서 발생한 총 블록 I/O를 말한다.
- 같은 SQL을 실행했을 때 시간이 달라지는 이유
- 논리적 I/O는 언제나 일정하다.
- 그러나 계속 실행할 수록 버퍼에 쌓이는 것이 많아 물리적 I/O가 줄어든다.
- 그렇기 때문에, 논리적 I/O를 줄임으로서 물리적 I/O를 줄이는 것이 곧 SQL튜닝이다.
Table Full Scan vs Index Range Scan
- 테이블 풀 스캔 : 모든 데이터 다 읽기
- 시퀀셜 엑세스와 멀티블록 I/O를 통해 한 블록의 속한 모든 레코드를 한번에 읽고 캐시에서 못찾으면 한번의 I/O를 통해 다음 수십 수백개의 블록을 한번에 가져온다.
- 소량의 데이터를 찾을 때는 비효율적이어서 반드시 인덱싱을 해야한다.
- 인덱스 레인지 스캔: 인덱스 사용해서 읽기
- 인덱스 기반을 사용하면 레코드 하나를 읽기 위해 매번 I/O를 해야하는 메커니즘이다. 그래서 많은 값을 찾을 때는 오히려 풀스캔이 낫다.
캐시 탐색 알고리즘
- 모든 블록 I/O는 메모리 버퍼 캐시를 경유한다.
- DBMS는 버퍼캐시를 해시 구조로 관리한다.
- 0 : 4 → 8 →
- 1 : 5 → 1
- 2 : 2
- 3 : 7 → 11
- 메모리 공유자원에 대한 엑세스 직렬화
- 버퍼캐시는 SGA에 포함되므로 모두 공유자원이다. 문제는 하나의 버퍼 블록에 두 개 이상 프로세스가 동시에 접근할 때 일어난다. (Race Condition과 비슷하다) 동시에 접근하면 블록 정합성에 문제가 생길 수 있다.
- 이를 위해 직렬화(serialization)를 사용한다.
- 한마디로 표현하면 줄세우기이다.
- 버퍼 캐시에 대한 동시 접근을 제어하는 저수준의 잠금 메커니즘. 래치는 한 프로세스가 버퍼 블록에 접근하는 동안 다른 프로세스가 동일한 블록을 수정하지 못하도록 한다. 이를 통해 Race Condition을 방지하고 데이터의 정합성을 유지할 수 있다.
- 버퍼 락
- 버퍼 캐시의 대한 래치는 원하는 값을 찾았을 때 래치를 푼다. 즉, 다음 프로세스가 캐시에 접근할 수 있다. 그런데 이전에 프로세스도 A블록을 수정중인데 다음 프로세스도 B블록을 수정하려 한다면 정합성에 문제가 생긴다. 그러므로 버퍼락으로 이것을 관리한다.