본문 바로가기

DB/Oracle

[Oracle] Chapter 3. 캐시와 공유메모리

3.1 어쨰서 캐시가 필요한 것인가?

 

디스크의 I/O 처리에 필요한 동작

 

1. 데이터가 디스크 안쪽에 있어 헤드를 안쪽으로 이동하고 안정될 때까지 기다림. 물론, 그 사이에도 디스크는 회전하고 있음

2. 디스크가 회전해 데이터가 존재하는 위치가 다가올떄까지 기다림

 

디스크는 액추에이터(톤암)를 움직여서 데이터를 읽고 쓴다. 오라클은 디스크에게 읽고 쓰는 것을 의뢰한다. 오라클은 여러 개의 프로세스로 구성되어 있고 SQL문을 동시에 처리할 수 있다. 또한 프로세스에는 각자의 역활이 있으며, SQL문을 빠르게 처리하기 위해 전념하는 서버 프로세스와 그것을 지원하는 백그라운드 프로세스가 존재한다.

1장에서 디스크가 동작하는 것은 매우 느리고 I/O 1회에 10~20밀리초 정도 걸린다고 설명했다. 그래서 오라클은 '캐시'라고 불리는 기술을 사용해 가능한 디스크에서 처리하지 않고, 메모리에서 처리하는 구조를 갖고 있다.

 

오라클의 구성(서버 프로세스와 백그라운드 프로세스)

서버 프로세스 : SQL 문을 처리함. 바꿔 말하면 오라클 클라이언트에게 서비스를 직접 제공하는 프로세스임

백그라운드 프로세스: 서버 프로세스와는 다르며, 오라클 클라이언트에게 서비스를 직접 제공하지는 않음. 전면에 나서지 않는 지원 스태프에 해당하는 프로세스

 

캐시는 가장 간다한 튜닝 항목이자 잘 알려진 기능 중 하나이지만, 아키텍처를 제대로 이해하고 있지 않으면 생각지도 못한 부분에서 '가져오고 싶었던 데이터가 캐시에 존재하지 않아 성능이 좋지 않다'와 같은 결과를 초래한다. 캐시의 동작을 잘 이해해서 DB의 성능을 올려주자.

 

3.2 그래서 캐시란 대체 무엇인가?

 

먼저 일반적인 IT용어로써 캐시가 무엇인지 알아보자.

일반적으로 캐시를 '작업장'이나 '작업대'에 비교하는 경우가 많다. 여러분이 일할 때 빈번하게 사용하는 도구나 책을 필요할 때마다 서랍이나 책장에서 꺼내어 사용하고, 끝나면 바로 다시 서랍이나 책장에 집어넣는 식으로 사용하는 분은 없을 것이다. 빈번하게 사용한다면 책상 위나 손이 잘 닿는 곳에 놓아 둘꺼다. 캐시의 목적도 이와 같다. 빈번하게 사용하는 데이터를 매번 디스크에서 꺼내오지 않고 캐시라고 불리는 메모리에 둠으로써 빠르게 사용할 수 있도록 하는 것이다.

메모리(캐시), 디스크, 그리고 CPU의 관계

CPU : 데이터는 여기(CPU)로 보내져 처리됨. 프로세스를 난쟁이에 비유한다면, 여기서 난쟁이가 일을 하고 있다는 의미

나노초 단위로 주고 받음

메인 메모리 : 프로세스가 사용한 메모리(변수 등)는 물론, 캐시도 여기에 놓여 있다.

데이터 A의 캐시 : 디스크의 데이터를 처리해야 할 때, 이 메모리(캐시)에 같은 데이터가 존재하면 디스크에서 읽을 필요 없이 CPU에게 데이터를 직접 건네줄 수가 있다.

밀리초 단위로 주고받음

디스크(데이터 A) : 디스크는 가격이 가장 저렴함. 데이터는 디스크에 저장되고 필요에 따라 꺼내어 사용됨

다음으로 오라클에서의 데이터 캐시('버퍼 캐시'라고 불린다) 동작을 살펴보자. 서버 프로세스가 원하는 데이터가 버퍼 캐시에 존재할 떄와 존재하지 않을 때의 차이를 확인하자. 캐시에 히트(hit)하지 않았을 떄는 처리 속도가 느린 디스크에서 데이터를 읽어올 수밖에 없으므로 그만큼 SQL의 처리가 늦어진다.

 

버퍼 캐시에 히트(데이터가 존재)할 떄

- 캐시를 히트하면 처리 속도가 느린 디스크를 사용할 필요가 없기 떄문에 SQL문의 처리 속도가 빨라진다.

버퍼 캐시에 히트하지 않을(데이터가 존재하지 않을)떄

- 캐시에 히트되지 않으면 처리 속도가 느린 디스크에서의 읽어올 수밖에 없으므로 그만큼 SQL의 처리가 느려진다.

 

3.3 데이터는 블록 단위로 관리

 

오라클은 '블록'이라고 하는 단위로 데이터를 관리한다. I/O의 단위도 블록을 기반으로 하고 있으며, 버퍼 캐시도 블록 단위로 관리하고 있다. 블록은 단순하게 '정리용 상자'라고 생각하면 된다. 일상생활에서도 크기가 작고 양이 많은 물건들을 정리할 떄는 상자를 몆 개 준비하고 그 안에 보관하는 경우가 많다. 오라클의 데이터는 수 바이트에서 수천 바이트 이상의 여러 '로우(행)'로 존재하므로, 오라클 역시 블록이라고 하는 정리용 상자를 준비해서 보관하는 것이다.(OS의 블록이 아니라 오라클의 독자적인 블록을 말한다.)

한 개의 블록에는 여러 건의 데이터가 보관돼 있으므로 한 건만을 디스크에서 읽어오려고 해도 필요한 데이터를 포함하고 있는 블록 전체가 캐시에 보관된다. 또한, 블록 크기는 2KB, 4KB, 8KB, 16KB, 32KB 중에서 선택할 수 있다. 데이터와 캐시의 크기가 커짐에 따라 최근 시스템에서는 8KB를 채용하는 일이 많아 졌다. 단, 크기가 큰 테이블을 시퀀셜 액세스로 읽어 와야 하는 DW(Data Warehouse, 데이터 웨어하우스) 등에는 16KB나 32KB 같은 크기를 선택할 떄도 있다.

 

3.4 캐시를 사용해서 인덱스 검색을 효율적으로

 

테이블뿐만 아니라 인덱스도 블록으로 구성되어 있다. 인덱스를 한 블록에 ㅂ관할 수 없을 때는 여러 개의 블록으로 구성하낟. 인덱스의 크기가 매우 작지않은 한 계층을 가진 구조가 된다.

여기서 인덱스를 3계층이라고 가정하고 인덱스를 사용해 테이블에서 데이터를 한건만 꺼내오는 SQL문에 걸리는 시간을 예측해보자. 테이블의 한 블록을 포함해 총 네 블록을 처리하지 않으면 안 되므로 I/O 한 번당 10밀리초라고 가정하면, 캐시에 적재되어 있지 않을 때는 I/O만 40밀리초가 걸리게 된다. 그것에 비해 이런 간단한 SQL을 처리하는 데 CPU 시간은 1.2밀리초 정도를 사용한다.(여기에서 CPU 시간은 가정한 값으로 CPU의 종류나 블록, OS, 각 조건들에 따라 달라질 수 있다.) 즉, 캐시에 데이터가 없을 때 걸리는 처리 시간은 41.2밀리초이고, 캐시에 데이터가 있을 떄 걸리는 처리 시간은 1.2밀리초이다. 캐시의 효과가 얼마나 좋은지, 캐시에 왜 신경을 써야 하는지 그 이유를 이해했을 것이라 생각한다.

 

3.5 프로세스는 캐시를 공유

 

프로세스마다 캐시를 가지면 낭비가 많아지고, 다른 프로세스에서 변경된 데이터를 볼 수 없는 등, 여러 문제가 발생한다. 그래서 어떠한 오라클 프로세스라도 볼 수 있는 메모리를 캐시로서 활용한다.

이미 알고 계신 분도 있을 것으로 생각하지만, OS에서 다른 프로세스의 메모리를 보는 것은 기본적으로 불가능하다. 왜냐하면 OS가 메모리 안의 데이터를 손상되지 않도록 보호하고 있기 떄문이다. 이러면 DBMS 입장에서는 불편함이 발생할 수밖에 없으므로, OS는 '공유 메모리'라는 특수한 메모리 기능을 제공한다. 공유 메모리를 사용하면 자신의 메모리 영역에 기록했던 데이터를 다른 프로세스에서도 즉시 볼 수 있다.

공유 메모리를 이해하기 위한 중요한 포인트는 '실제 메모리는 한 개다'라는 개념이다. 각 프로세스에게는 마치 자신의 메모리인 것처럼 보이지만, 실제로는 모든 프로세스가 같은 메모리 여역에 접근하고 있는 것이다. 오라클에서는 이런 공유 메모리를 'SGA(System Global Area)', 공유하지 않는 메모리의 일부를 'PGA(Program Gobal Area)'라고 부른다.(PGA는 서버 프로세스마다 존재하는 메모리이며, 각 서버 프로세스 고유의 데이터를 보관한다. SGA는 프로세스가 공유해야 하는 데이터를 보관하는 메모리이다.)

 

DBMS에게 공유 메모리는 매우 편리한 도구이기도 하며, 다수의 프로세스로 구성된 DBMS이기에 없어서는 안 될 필수 기능이기도 하다. 하지만 이 공유 메모리에는 누구든지 접근할 수 있으므로 Lock을 걸어서 배타적 제어(exclusive control)를 하지 않으면 데이터에 손상을 입을 수도 있다. 물론, 실제로 내부를 들여다보면 Lock을 통해 데이터를 보호하고 있다. 이 말은 곧 DBMS가 Lock이 복잡하게 얽힌 내부 구조를 가지고 있으며, 내부에서 사용하는 Lock으로 인해 성능 문제가 발생하기 쉽다는 것을 의미하기도 한다.

 

내부적인 Lock이 필요한 이유

- 어쩌다가 같은 메모리를 동시에 변경하려고 하면 변경된 데이터는 둘 중 하나가 원했던 데이터는 아니다. 따라서 내부에서 Lock을 사용해 문제가 발생하지 않도록 방지한다.

 

3.6 공유 메모리에 필요한 설정

 

오라클의 설정 파일인 spfileXXXX.ora(XXXX에는 데이터베이스를 식별하는 ID가 들어간다)에는 버퍼 캐시의 크기를 결정하는 'DB_CACHE_SIZE'라는 파라미터가 있다.(버퍼 캐시의 크기를 설정하는 파라미터 중 'DB_BLOCK_BUFFERS'는 오라클 12.2부터는 권고하지 않는다.) 앞에서 설명한 것처럼 버퍼 캐시는 성능과 직결되기 떄문에 크기를 정할 떄 신중히 결정해야 한다. 또한, 공유 메모리에는 버퍼 캐시뿐만 아니라 공유 풀이나 로그 버퍼 같은 영역도 존재한다.

일부 OS에서 오라클을 설치할 떄는 리스트 3.1과 같은 설정을 수행할 필요가 있다.

리스트 3.1 공유 메모리의 설정 예(리눅스의 경우)

# /sbin/sysctl -a | grep shm
kernel.shmall = 2097152
kernel.shmmax = 4294967295
kernel.shmmni = 4096
-- 'shm'으로 시작하는 부분이 공유 메모리의 설정

일반적으로는 매뉴얼에 따라서 설정해두면 문제가 없다. 또한, 이 설정 값은 각 OS마다 설정이 다르므로 오라클 메뉴얼을 참고하자. DBA(DataBase Administrator, 데이터베이스 관리자)라면 오라클미디어(우리나라에서는 미디어보다 오라클 다운로드 사이트(https://download.oracle.com) 및 오라클 지원 사이트(https://support.oracle.com)에서 다운로드하여 설치하는 경우가 많으므로 별도로 반드시 확인하자. 또한, 오라클과 관련된 문서는 공식 사이트(https://docs.oracle.comen/database/database.html)에서 찾을 수 있다. 해당 주소는 오라크르이 사정에 따라 변경될 수 있으니 주의하자.)에 동봉된 릴리즈 노트나 각 OS용으로 나온 오라클 매뉴얼은 반드시 읽기를 권장한다. 제한 사항이나 신경 쓰지 않으면 안 되는 부분들이 적혀 있다.

 

칼럼

 

버퍼 캐시의 크기와 관련된 최근의 이야기

 

지금까지 설명했던 것처럼 버퍼 캐시의 설정은 성능에 직결되는 중요한 부분이다. 그렇기때문에 여러분께서는 '그럼 대체 어떻게 버퍼 캐시의 크기를 정해야 하는가?'라는 의문이 들 것이다.

데이터베이스를 새로 설치할 떄와 같이 적절한 크기를 알 수 없는 경우에는 임시로 처음 크기를 크게 잡아 놓는다. 그 후에 대표적인 업무를 실제로 돌려보면서 관련된 통계를 기반으로 조정하는 방법이 있다.

그때 도움이 될 수 있는 힌트를 드리면, 버퍼 캐시 크기마다 물리 읽기 수를 예측하는 버퍼 캐시 어드바이저(V$DB_CACHE_ADVICE)나 버퍼 캐시 내에서 요청받은 블록을 꺼내온 빈도를 의미하는 버퍼 캐시 히트율이 있다.

또한, 버퍼 캐시를 아예 설정하지 않는 접근 방법도 있다. 부하의 정도에 따라 오라클이 자동으로 조절하도록 설정하는 방법이다. 공유 메모리(SGA)에는 버퍼 캐시 이외에도 SQL의 파싱 결과를 보관하는 공유 풀과 같은 다른 영역이 존재하며, 각각 설정하게 될 경우 크기를 하나하나 검토해야 한다. 이런 영역들의 크기를 개별적으로 설정해서 관리하는 것이 아니라 SGA만 크기를 설정해 놓으면 나머지는 오라클이 알아서 관리하는 것을 '자동 공유 메모리 관리(Automatic Shared Memory Management)'라고 부른다(PGA 내의 영역을 자동으로 관리하는 '자동 PGA 메모리 관리(Automatic PGA Memory Managerment)'나. SGA와 PGA 간의 비율도 자동으로 조정하는 '자동 메모리 관리(Automatic Memory Management)'라는 기능도 있다).

 

이 기능들을 사용하면 크기를 예측하느라 고생하지 않아도 부하의 정도에 따라 오라클이 알아서 조정해주기 떄문에 최근에는 자동으로 설정해놓고 사용하는 곳들도 많아지는 추세이다. 다만, 자동 공유 메모리를 설정 할떄는 DB_CACHE_SIZE를 함께 설정하는 것을 추천한다. 자동 공유 메모리를 설정한 상태로 DB_CACHE_SIZE를 설정하면 하한값으로서 동작하므로 혹여라도 버퍼 캐시의 영역이 다른 영역에 잡아먹혀서 성능이 나빠지는 상호아을 방지할 수 있기 떄문이다.

 

3.7 공유 메모리는 어떤 식으로 보이는가?

공유 메모리가 특수한 메모리나는 것은 충분히 이해할 것이라 생각한다. 공유 메모리는 ps 같은 명령어를 통해 확인한 결과에서도 특수하다는 것을 알 수 있다. 모든 프로세스마다 공유 메모리를 포함하여 보여주는 OS도 있고, 전혀 포함하지 않고 보여주는 OS도 있다.

 

리스트 3.2 ps 명령어로 본 각 프로세스의 메모리 크기(리눅스)

USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
oracle 18004 0.0 0.2 118764 18856 pts/0 S+ 11:20 0:00 sqlplus
oracle 19022 0.0 0.7 3175564 54616 ? Ss Sep01 1:14 ora_pmon_ORCL
oracle 19024 0.0 0.7 3175564 54544 ? Ss Sep01 0:26 ora_clmn_ORCL
oracle 19026 0.0 0.7 3175564 57500 ? Ss Sep01 3:46 ora_psp0_ORCL
oracle 19028 1.6 0.7 3175564 57496 ? Ss Sep01 350:98 ora_vktm_ORCL
oracle 19032 0.0 1.1 3195124 84760 ? Ss Sep01 1:19 ora_gen0_ORCL
oracle 19034 0.0 0.7 3175564 57956 ? Ss Sep01 0:26 ora_mman_ORCL
oracle 19038 0.0 0.7 3297592 58616 ? Ssl Sep01 6:35 ora_gen1_ORCL
oracle 19041 0.0 0.7 3175564 54340 ? Ss Sep01 0:51 ora_diag_ORCL
oracle 19043 0.0 0.7 3297588 56568 ? Ssl Sep01 0:23 ora_ofsd_ORCL

 

VSZ : 각 프로세스의 가상 메모리 크기(KB)

RSS : 각 프로세스가 실제로 사용하는 메모리으 크기(KB)

리스트 3.2에서 가상 메모리의 크기(VSZ)를 보면 각 프로세스가 3GB 정도 사용하고 있는 것이 보이고, 모든 프로세스의 크기를 합하면 마치 대량의 메모리를 사용하고 있는 것처럼 보인다. 하지만 실제로 대량의 메모리를 사용하고 있는 것은 아니며, 공유 메모리의 사용량을 중복해서 표기하기 떄문에 나타나는 현상이다.

 

칼럼

 

'세마포어(semaphore)'란

 

세마포어는 OS가 제공하는 자원을 관리하기 위한 장치의 일종으로, 자원의 수에 비해 사용하고자 하는 프로세스의 수가 많을 경우에 순서대로 자원을 사용할 수 있도록 프로세스 제어를 수행한다. 여러 개의 프로세스가 동작하는 오라클도 프로세스 제어에 세마포어를 사용하고 있다.

 

리스트 3.A OS에서 수행하는 세마포어 확인 방법(리눅스)

# /sbin/sysctl - a | grep sem
kernel.sem = 250 32000 100 128
- 이 'sem'으로 시작하는 설정이 세마포어의 설정

기본적으로 세마포어도 매뉴얼에서 지시하는 대로 설정하면 문제는 없지만, 오라클 이외의 애플리케이션에서 사용할 수도 있으므로 오라클을 기동할 때 세마포어가 부족하다는 의미의 메세지가 나타나면 늘리는 것을 검토해야 한다. 또한, 아무도 사용하지 않는 세마포어가 OS에 남아 있는 경우도 있으므로 정리할 필요가 있다. 그럴 때는 DBA가 ipcs 명령어나 ipcrm 명령어를 사용해서 정리하면 된다.

 

3.8 버퍼 캐시를 정리하는 LRU 알고리즘

 

버퍼 캐시는 자주 사용하는 데이터를 더 빠르게 가져오기 위해 존재한다. 또한, 버퍼 캐시의 크기는 한정되어 있으므로, 누군가가 어떤 식으로든 관리하고 정리해야 한다. 캐시에 사용하는 알고리즘 중 일반적으로 알려진 것이 'LRU(Least Recently Used) 알고리즘'이다. 단순하게 설명하면 최근에 사용하지 않은 데이터부터 캐시 아웃(버린다)하는 알고리즘이다. 오라클도 버퍼 캐시 관리에 이 LRU 알고리즘을 사용한다. 오라클은 LRU를 토대로 블록의 목록을 가지고 있으며, 어떤 블록이 최근에 사용되지 않았는지를 파악하고 있다.

 

데이터를 읽어오는 것만이라면 이 동작으로도 충분하지만, 오라클의 서버 프로세스는 변경한 데이터(블록)도 캐시에 둔다. 이는 2장에서 '기본적으로 서버 프로세스는 디스크에서 데이터를 읽어오기는 하지만 디스크에 기록은 하지 않는다'고 설명했던 부분의 동작이다. 그렇다면 누가 디스크에 데이터를 기록할까?

답은 백그라운드 프로세스인 DBWR이다. 단, 변경한 데이터는 디스크에 기록하기 전에 캐시에서 버리면 데이터가 손실되므로, 캐시에서 버려지기 전에(가능하면 정기적으로) 디스크에 기록해둘 필요가 있다. 그래서 DBWR은 정기적으로 변경한 데이터를 디스크에 부하를 주지 않도록 조심하면서 디스크에 저장한다.

또한, 자주 사용하지 않는 데이터를 버퍼 캐시에 둘 필요는 없다. 구체적인 예를 들자면, 데이터가 많은 테이블을 풀 스캔한 데이터는 적재해두더라도 사용하는 경우는 별로 없으며, 오히려 풀 스캔한 데이터를 적재해 둠으로써 자주 사용하는 데이터를 캐시에서 쫒아내는 일이 발생하게 된다. 따라서 오라클은 큰 테이블이라고 판단하면 버퍼 캐시로 블록(데이터)을 적재하지 않으며, 풀 스캔했을 때의 데이터는 일반적으로 버퍼 캐시에 적재되지 않는다고 생각하자.

 

3.9 오라클뿐만이 아닌 OS나 스토리지에 대해서도 생각하자

 

최근 주목받고 있는 것이 스토리지의 캐시이다. 스토리지에서 데이터를 읽어오는 것은 당연히 빨라지지만, 캐시 덕분에 기록하는 것도 빨라진다. 그 이유로는 원래 디스크에 기록해야 하는 데이터를 캐시에 기록하는 것만으로도 OS관점에서의 I/O를 종료할 수 있기 떄문이다.

스토리지 캐시 : 스토리지의 캐시에 기록한 데이터가 유실되어서는 안 되므로, 이중화나 비휘발성 메모리를 사용하는 등의 장치가 고안되어 있다. 그래서 스토리지의 캐시는 가격이 많이 높다.

 

3.9.1 OS의 버퍼 캐시와 가상 메모리의 차이

OS에는 버퍼 캐시(파일 캐시나 페이지 캐시라고 부르기도 하지만, 여기서는 버퍼 캐시라고 부르겠다.)와 가상 메모리라고 불리는 기능이 있다. 이 두 가지 기능과 오라클의 버퍼 캐시는 같은 것으로 생각해야 한다. OS의 버퍼 캐시는 오라클의 버퍼 캐시와 비슷한 기능을 가지고 있다.

OS에서 가상 메모리라는 기능을 이용해 실제로 가지고 있는 물리 메모리보다 더 많은 메모리를 사용할 수 있다. 이 기능은 메모리에서 자주 사용되지 않는 데이터를 디스크에 저장한다. 프로세스 관점에서 데이터는 메모리에 있는 것처럼 보이지만, 실제는 디스크에 저장된 구성이다.

 

가상 메모리와 페이징(paging)

- 최근에 사용하지 않은 데이터를 프로세스 몰래 디스크에 보관해둔다. 이것으로 메모리가 실제 메모리보다 많은 것처럼 보인다(가상 메모리 기능)

1. 최근에 데이터를 사용하지 않아 디스크로 옮겼음

2. 메모리에 접근(데이터 요청)

3. 프로세스가 요청해서 다급하게 디스크에서 읽어 옴

1, 3 동작을 페이징(paging)이라고 말하며, 이는 물리 메모리와 디스크 사이에서 블록(페이지)을 주고받는 것을 의미한다. 물리 메모리의 페이지를 디스크에 기록하는 것을 페이지 아웃(page out), 디스크의 페이지를 물리 메모리로 읽어오는 것을 페이지 인(page in)이라고 한다.

가상 메모리는 버퍼 캐시와는 반대로 동작하도록 구현되어 있다. 버퍼 캐시(OS든 오라클이든)는 디스크에 빠르게 접근하기 위해 메모리의 일정 부분을 할당하여 사용한다. 이것에 비해 속도가 느려지더라도 사용할 수 있는 메모리의 크기를 늘리기 위해서 디스크를 사용하는 것이 가상 메모리이다.

 

일반적으로는 이 세 가지 기술 간의 관계를 신경 쓸 일은 없을 것 같아 보인다. 그러나 다시 한번 곰곰이 생각해보면 밀접한 관계가 있음을 알 수 있다. 예를 들어, 오라클의 버퍼 캐시를 물리 메모리보다 많게 설정한다고 가정해보자. 가상 메모리를 사용해서 버퍼 캐시를 물리 메모리보다 크게 설정할 수는 있지만, 의도했던 바를 실제로 달성했다고 말할 수 있을까? 그렇지 않다. 왜냐하면 버퍼 캐시를 사용하여 메모리를 고속화한다는 목적이 페이징으로 인해 상쇄되어 버리기 떄문이다. 물론, OS의 버퍼 캐시도 마찬가지라고 할 수 있다.

- 물리 메모리가 충분하지 않으면 메모리에 있는 것처럼 보여도 실제로는 데이터가 스왑에 존재할 수 있다. 오라클의 버퍼 캐시를 무리해서 크게 잡아 버퍼 캐시가 스왑에 들어가 버린다면 어떨까?

-> 버퍼 캐시가 존재하기 떄문에 디스크에서 읽지 않아도 되지만, 버퍼 캐시 자체가 디스크에 들어가 있다. 이래서는 의미가 없다.

 

최근에는 메모리의 가격이 저렴하기 떄문에 장비에 물리 메모리를 충분히 할당한후, 오라클이 물리 메모리만을 사용할 수 있도록 파라미터를 설정할 것을 권한다. 즉, 가상 메모리를 사용하기 위한 디스크는 보험으로 준비해두는 정도이며, 실제로는 사용하지 않을 것을 추천한다.(예전에는 스왑(가상 메모리를 위한 디스크)의 크기를 물리 메모리의 2~4배 정도로 할당하는 설계를 했던 시기도 있었다. 하지만 이미 설명한 바와 같이 최근엔 그렇게 큰 스왑을 만들지 않는 설계도 늘어나기 시작했다.)

 

리스트 3.3 오라클을 재기동했는데 I/O의 속도가 빨라지는 수수께끼

 

정답은 'OS의 버퍼 캐시에 데이터가 적재되어 있기 떄문'이다. 오라클을 재기동했다 해도 OS는 재기동하지 않았다. 즉, OS의 버퍼캐시에 데이터가 남아 있었다는 의미이다.

이전까지는 이상해 보이기만 했던 현상들이 OS나 스토리지, 오라클의 아키텍처나 동작을 공부하다보면 서서히 이해되기 시작하고, 더 나아가서는 다양한 상황에도 잘 대처할 수 있게 된다. 여러 번 성능 테스트를 수행하고 결과를 검토할 때 '테스트 결과 중 성능이 안 좋았던 결과는 한 번이었으니 특이사항은 없는 것 같다'라며 해당 결과를 무시하는 엔지니어를 종종 만날 수 있다. 만약 아키텍처를 잘 이해하고 'OS의 캐시에 의해 두 번쨰부터는 빠르게 처리되고 있는 것처럼 보일 뿐'이라는 것을 알았다면 제대로 대처할 수 있지 않을까?

현장에서 오라클을 사용할 때는 이번 장에서 설명한 아키텍처나 동작의 이미지를 떠올리면서 '캐시의 데이터를 사용하기 위해서는 어떻게 하는 것이 가장 좋을까?'를 고민하며 설계와 튜닝을 진행해야한다. 이떄 OS와 스토리즈이 캐시나 동작까지 고려해서 진행한다면, 분명 더 좋은 설계나 해결책을 찾을 수 있을 것이다.