l9791185890302

원문 : 『그림으로 공부하는 오라클 구조 개정판』 , 스기타 아츠시 외 4명 지음, 제이펍

오라클을 이해하기 위한 필수 키워드

  1. 병렬 처리를 가능케 하고 높은 처리량을 실현한다.
  2. 응답 시간(response time)을 중시한다.
  3. 커밋(COMMIT)한 데이터는 지킨다.

오라클과 디스크(하드디스크)

hard_drive_parts

오라클은 디스크에서 데이터를 읽어오고 필요한 처리를 한 후 다시 디스크에 기록한다. 그렇기 때문에 오라클과 디스크는 뗄 수 없는 관계다. 디스크는 항상 회전하고 있고 그 위로 헤드가 움직여서 데이터를 읽거나 기록한다.

디스크 동작

disk_latency

데이터를 읽기 위해서는 데이터가 저장되기 시작한 첫머리를 찾아야한다. 이렇게 위치를 찾는 작업을 탐색(seek, 시크)라고 한다. 이 후에 원하는 정보를 읽을 수 있는 위치가 회전해서 다가올때 까지 기다리다가 해당 위치에 오면 데이터를 읽고 쓴다.

디스크에 접근할 때는 밀리초(ms) 단위의 시간이 필요하다. 컴퓨터 입장에서는 매우 느린 속도다.

I/O 대기시간 줄이기

시퀀셜(sequential)은 순차를 뜻하며 시퀀셜 액세스(sequential access)는 시작점에서부터 마지막까지 중간 부분을 빠트리지 않고 전부 액세스(읽기/쓰기)하는 것을 말한다. 메모리에 테이블의 데이터가 없으면 풀 스캔(Full Scan) 할 때 시퀀셜 액세스가 발생한다.

데이터 전송속도가 20MB/초 라고 가정했을 때 1GB 데이터를 가져오는데 50초가 걸린다. 그래서 인덱스(index, 색인)이라는 것이 나오게된다. 인덱스는 검색할 때 사용하는 키 값과 그 키가 존재하고 있는 위치가 기록되어 있다.

인덱스 사용 예

SELECT "소속 회사" FROM "개인 데이터" WHERE "이름" = "래리";

인덱스를 사용해서 이 SQL을 처리할 때는 ‘‘이름’이 기록되어 있는 인덱스를 조사한다. 그 결과로 주소(ROWID)를 알아낼 수 있고, 그 주소를 토대로 데이터를 읽어온다.

인덱스 sql

인덱스 크기가 커지면 작업에 필요한 시간이 늘어나지는 않는다. 오라클 인덱스는 ‘인덱스에 인덱스를 추가하는 것’처럼 여러 계층으로 구성되기 때문이다. 이렇게 여러 계층으로 구성된 구조를 트리 구조라고 부른다.

oracle tree

랜덤 액세스

인덱스를 사용할 때 필요한 부분만 읽어오면 충분하지만 디스크 위에 연속적으로 존재하는 경우는 거의 없다. 따라서 헤드를 움직여가면서 띄엄띄엄 접근하게 되고 이를 ‘랜덤 액세스(random access)’라고 한다.

디스크 관점에서는 비효율적인 부분이 존재한다. 오라클 블록 크기가 8KB라고 가정, 1초에 탐색할 수 있는 횟수를 100회라 가정할때 1초에 최대 800KB를 액세스하게 된다. 이는 매우 느린 속도다.

이러한 탐색을 반복하기 때문에 DBMS에서 사용하는 디스크는 IOPS(I/O Per Sec, 초당 수행 가능한 I/O의 횟수) 지표가 중요하다. 그리고 대부분 디스크는 IOPS가 100회나 200회 정도이기 때문에 한 개나 두 개의 디스크만으로 데이터베이스를 구성하면 부하가 발생했을 때 요청이 오는 것을 탐색이 따라잡을 수 없는 병목 현상이 발생한다.

데이터를 보증하기 위한 디스크

데이터는 오라클 프로세스가 비정상 종료되어도 무사해야한다. 이 점이 DBMS와 다른 프로그램과의 차이점이다. 오라클은 데이터를 변경한 후에 COMMIT 이라고 입력하면 데이터를 디스크에 기록한다.

tip) 인덱스를 사용하는 것이 유리한 경우는 어째서 필요한 데이터가 전체 데이터의 15% 미만이라고 하는 걸까?

테이블의 데이터가 대량이고 그중 한 개의 로우를 꺼내야 한다면 당연히 인덱스를 통한 액세스가 빠르다

하지만 모든 데이터를 보려고 할 때 매번 인덱스를 찾은 후 데이터를 찾아가면 오히려 속도가 느려진다.

만일 데이터가 50%라면 어떨까? 여기서 중요한 점은 ‘디스크에서 랜덤 액세스는 데이터를 읽어오는 효율성이 시퀀셜 액세스 보다 떨어진다’라는 특성이다. 테이블에 2만 건인 데이터가 있고 그중 절반인 1만 건을 꺼낸다고 가정한다. 여기서 한 로우는 8KB이다. 지금까지 사용해 왔던 디스크의 성능을 기준으로 계산해보면, 랜덤 액세스로 약 100초가 걸린다. 그것과 비교하면 2만 건 전부를 읽어온다해도 약 8초면 끝난다. 즉, 디스크 특성상 모든 데이터가 아니더라도 일정 크기 이상의 데이터를 읽는다면 시퀀셜 액세스를 사용하여 테이블을 풀 스캔하는 편이 빠르다.

단, 실제로는 캐시에 데이터가 보관된 경우가 있다. 한 개의 블록에 여러 로우의 데이터가 보관되어 있는 경우도 있다. 인덱스의 데이터를 디스크에서 읽어 와야 하는 경우도 있으므로 15%가 임계치라고 단순하게 말할 수는 없다.

‘시퀀셜’의 의미

시퀀셜 액세스는 ‘db file scattered read’라고 표시된다.

랜덤 액세스는 ‘db file sequential read’라고 표시된다.

‘scattered’는 분산됐다 라는 의미이고 sequential은 연속적인의 의미를 가지고있다.

오라클은 블록 단위로 데이터를 읽고 쓰며, 메모리에 배치해둔다.

시퀀셜 액세스는 여러 블록을 한꺼번에 빠짐없이 읽어온다. 이때 읽어온 여러 블록은 메모리상에 연속되지 않은 형태로 놓인다. 따라서 ‘scattered’라고 표현한다.

랜덤 액세스는 읽어오는 데이터 블록은 한 번에 한 개이며 메모리 공간에 반드시 연속적으로 놓이게된다. 따라서 ‘sequential’이라고 표현한다.

따라서 시퀀셜 액세스는 디스크 액세스를 할 때 연속적으로(sequential) 데이터를 가져오지만 메모리에는 분산(scattered)된 형태로 놓이고, 랜덤 액세스는 디스크에서 분산된(scattered) 데이터를 가져오지만 메모리에는 연속적인(sequential) 형태로 놓이게 된다.