1. 오라클을 이해하기 위한 필수 키워드
✔️ 병렬 처리를 가능하게 하고 높은 처리량을 실현
✔️ 응답 시간(response time) 중시
✔️ 커밋(commit)한 데이터 지키기
이 세 가지 특성은 서로 상반된 성향이 있어 동시에 모두 만족시키기 어려운 개념이다.
이러한 특성을 기억하면서 시작해보자.
2. 오라클과 디스크(하드디스크)
오라클은 디스크에서 데이터를 읽어오고, 필요한 처리를 한 후 다시 디스크에 기록합니다. (중략) 그래서 오라클과 디스크는 떼려야 뗄 수 없는 관계입니다.
턴테이블에 레코드를 올려 놓은 이미지를 떠올리면 이해가 쉽다.
그림 1.2의 액추에이터는 턴테이블의 톤암에 해당하고, 헤드는 턴테이블의 카트리지 바늘에 해당한다.
디스크는 거의 항상 회전하며, 그 위로 헤드가 아주 빠르게 움직여서 데이터를 읽거나 기록한다.
(게다가 1분에 1만 번 회전이라니!!)
3. 디스크의 동작
디스크에서 데이터를 읽어오기 위해서는 원하는 데이터의 시작 시점(첫머리)를 찾는 것부터 시작이다.
이 작업을 seek(탐색) 이라고 한다.
이렇게 시작 지점을 찾았다면 디스크가 회전해서 이 위치(특정 데이터의 첫머리)가 다가올 때까지 기다리다가 다가오면 데이터를 읽고 쓴다.
이렇게 기다리는 시간을 rotational latency time(회전 대기 시간) 이라고 한다.
보통 필요한 데이터는 디스크의 안쪽에 있으므로 헤드를 안쪽으로 이동시켜야 한다.
이렇게 디스크에 접근할 때는 밀리초(ms) 단위의 시간이 필요하다. (메모리는 나노초 단위(ns))
메모리는 전기 신호로 작업하지만 디스크는 물리적인 동작(기계 동작)이 필요하기 때문이다.
그래서 이 I/O 시간을 줄이는 것이 중요한 목표라고 할 수 있다.
예시를 가지고 이해해보자.
탐색 시간과 회전 대기 시간이 총 10ms가 걸린다고 가정하자.
디스크의 전송 속도는 20MB/s 이다.
3.1 I/O 대기 시간 줄이기
먼저 시퀀셜 액세스 개념에 대해 알아야 한다.
시작점부터 마지막까지 어느 한 부분도 빠트리지 않고 전부 액세스(r/w)하는 것이다.
메모리에 테이블의 데이터가 없으면 full scan 할 때 시퀀셜 액세스가 발생한다.
테이블의 크기가 1GB이고 모든 데이터를 가져올 때 시퀀셜 액세스가 발생하면 50s가 소요된다.
성능이 좋지 않다.
이 때 사용할 수 있는 것이 바로 인덱스 개념이다.
3.2 인덱스의 사용 예
간단하게 인덱스를 사용하는 예를 살펴보자.
SELECT 소속회사
FROM 개인 데이터
WHERE 이름 = "래리";
이름 컬럼에 인덱스가 걸려있다면 모든 데이터를 full scan할 필요 없이 이름 컬럼의 값이 '래리'인 데이터만 조사하면 된다.
➕ 오라클의 인덱스는 '인덱스에 인덱스를 추가하는 것' 처럼 여러 계층으로 구성되게 되고, 이러한 구조를 '트리 구조'라 부른다.
📣TIP
인덱스를 사용하는 것이 유리한 경우는 필요한 데이터가 전체 데이터의 15% 미만일 때다?
이유가 뭘까?
시퀀셜 액세스와 랜덤 액세스의 특성을 살펴보면 알 수 있다.
대량의 데이터에서 한 개의 row를 꺼내야 한다? 그럼 인덱스를 통한 액세스가 빠르다.
하지만 모든 데이터를 봐야 한다? 인덱스를 찾은 뒤 데이터를 찾아가면 오히려 속도가 느려진다, (색인을 일일이 찾아가면서 모든 내용을 본다? 너무 비효율적인 방법이다)
그렇다면 데이터의 50%를 볼 때에는?
여기서 중요하게 봐야할 점은 디스크에서의 랜덤 액세스는 데이터를 읽어오는 효율성이 시퀀셜 액세스보다 떨어진다 라는 점이다.
지금까지 썼던 계산법을 사용해서 살펴보면
테이블 데이터가 2만 건이고 그 중 1만 건을 꺼낼 계획일 때, 한 로우의 크기가 8KB인 상황에서
랜덤 액세스로는 약 100초가 걸린다.
하지만 시퀀셜 액세스는 약 8초가 걸린다.
➡️ 디스크 특성 상 모든 데이터가 아니더라도 일정 크기 이상의 데이터를 읽어올 때는 시퀀셜 액세스를 사용하는 것(full scan)이 빠르다.
3.3 랜덤 액세스
인덱스를 사용하면 필요한 부분만 읽어오면 되지만, 실제 디스크에서는 필요한 부분만이 연속적으로 존재하는 경우가 없다.
그러므로 헤드를 움직여가면서 비연속적으로 접근하게 된다.
이런 방식을 랜덤 액세스라고 한다.
이렇게 설명만 봐도 비효율적인 것 같다는 느낌이 든다. 비연속적으로 접근하게 되면 그 과정에서 불필요한 시간이 소요되기 때문이다.
(첫머리를 찾아다니느라 낭비하는 시간이 생긴다)
탐색을 반복하므로 DBMS에서 사용하는 디스크는 IOPS(I/O Per Sec) 지표가 중요하다. (대부분의 DBMS는 IOPS가 100 또는 200회 정도)
한 개나 두 개의 디스크만을 사용해 DB를 구성하게 되면 집중적으로 부하가 발생하는 경우, 요청에 대한 탐색이 원활하게 이루어지지 못하게 된다. (탐색이 따라잡을 수 없게 되어 디스크에 병목 현상이 발생한다)
4. 데이터를 보증하기 위한 디스크
DBMS는 다른 프로그램들과는 다르게 프로세스가 비정상적으로 종료되어도(어떠한 장애가 발생해도) 데이터가 무사해야 한다.
이를 위해 DBMS 에서는 commit 을 사용해 데이터를 디스크에 기록한다.
이 부분에 대해서는 나중에 다시 살펴보자.