기억장치의 분류
일반적으로 기억장치는 기억비용에 따라 1차에서 3차까지의 계층으로 분류됩니다.
기억비용은 데이터를 저장하는데 소모되는 비용을 의미합니다.
1차기억장치의 경우 데이터 접근속도는 매우 빠르지만 기억비용이 높고 2차, 3차 기억장치로 갈수록 기억비용은 낮아지지만 데이터 접근속도가 느려집니다.
결국 많은 데이터를 영속적으로 저장하기 위해서는 속도를 잃고, 속도를 얻고자 하면 많은 데이터를 영속적으로 저장하기 힘들기 때문에 상황에 맞는 기억장치를 사용해야 합니다.
DBMS와 기억장치의 관계
DBMS는 데이터 저장을 목적으로 하는 미들웨어이기 때문에 기억장치와는 떨어뜨릴 수 없는 관계입니다.
하드디스크
DBMS가 데이터를 저장하는 매체(저장소)는 현재 대부분 HDD입니다. 물론 하드디스크 이외에도 많은 선택 사항있습니다.
하지만 용량, 비용, 성능의 관점에서 대부분 하드디스크를 선택하고 있습니다.
인메모리 데이터베이스와 같이 메모리에 저장하고 테이프 등의 매체를 이용해 백업하기도 하고 SSD를 이용해 저장하기도 합니다.
메모리
DBMS는 저장장치로 메모리도 사용합니다.
하지만 디스크에 비해 기억 비용이 굉장히 비싼데도 불구하고 메모리를 사용하는 이유는 DBMS의 성능 향상 때문입니다.
예를 들어, 자주 접근하는 데이터를 메모리 위에 올려두면 같은 SQL 구문을 실행한다고 해도 디스크에서 데이터를 가져올 필요 없이 곧바로 메모리에서 읽어 빠르게 데이터를 검색할 수 있습니다.
일반적인 SQL 구문의 실행시간 대부분은 저장소 I/O(입출력)에 사용하기 때문에 디스크 접근을 줄일 수 있다면 굉장히 큰 폭의 성능 향상이 가능합니다.
이렇게 성능 향상을 목적으로 데이터를 저장하는 메모리를 버퍼(buffer) 또는 캐시(cache)라고 부릅니다.
이렇게 고속 접근이 가능한 버퍼에 데이터를 어떻게, 어느 정도의 기간 동안 올릴지 관리하는 것이 DBMS의 버퍼 매니저입니다.
메모리 위에 있는 두개의 버퍼
DBMS가 데이터를 유지하기 위해 사용하는 메모리는 크게 다음과 같이 두종류가 있습니다.
- 데이터 캐시
- 로그 버퍼
대부분의 DBMS는 이러한 두 개의 역할을 하는 메모리 영역을 가지고 있습니다.
이러한 버퍼는 사용자가 용도에 따라 크기를 변경하는 것이 가능합니다.
다음은 메모리 크기를 Oracle, PostgreSQL, MySQL을 예로 정리한 표입니다.
데이터 캐시
데이터 캐시는 디스크에 있는 데이터의 일부를 메모리에 유지하기 위해 사용하는 메모리 영역입니다.
만약, 실행한 SELECT 구문에 선택한 데이터가 모두 데이터 캐시에 있다면 디스크와 같은 느린 저장소에 접근하지 않고 메모리에서 바로 처리되기 때문에 굉장히 빠르게 응답하게 됩니다.
로그 버퍼
로그 버퍼는 갱신 처리(INSERT, DELETE, UPDATE, MERGE)와 관련 있습니다.
DBMS는 갱신과 관련된 SQL 구문을 사용자로부터 받으면, 곧바로 저장소에 있는 데이터를 변경하지 않습니다.
일단 로그 버퍼 위에 변경 정보를 보내고 이후 디스크에 변경을 수행합니다.
이처럼 데이터베이스의 갱신 처리는 SQL 구문의 실행 시점과 저장소에 갱신하는 시점에 차이가 있는 비동기 처리입니다.
DBMS가 이런식으로 갱신하는 시점에 차이를 두는 이유는 성능을 높이기 위해서입니다.
저장소는 검색 뿐만 아니라 갱신할 때도 상당한 시간이 소모되는데, 이때 사용자가 변경될 때까지 기다리는 경우 사용자는 장기간 대기하게 됩니다.
따라서 한 번 메모리에 갱신 정보를 받은 시점에서 사용자에게는 해당 SQL 구문이 끝났다고 통지하고 내부적으로 관련된 처리를 계속 수행하는 것입니다.
데이터 캐시와 로그 버퍼를 보면 알 수 있듯이 결국 DBMS는 저장소의 느림을 어떻게 보완할 것인가? 라는 것을 해결하기 위한 미들웨어입니다.
이러한 고민을 해결하기 위해 복잡한 버퍼 메커니즘을 탑재하게 된 것입니다.
만약, 저장소가 빠른속도를 지원했다면 이런 구조를 사용하지 않아도 됐을 것 입니다.
메모리의 성질이 초래하는 트레이드 오프
메모리는 가격이 비싸서 보유할 수 있는 데이터의 양이 상대적으로 적은 것이 대표적인 단점입니다.
이외에도 다음과 같은 단점이 존재합니다.
휘발성
메모리에는 데이터의 영속성이 없습니다.
즉, 하드웨어 전원을 꺼버리면 메모리에 올라가 있는 모든 데이터가 사라지게 되는데 이런 성질을 휘발성이라고 부릅니다.
그래서 DBMS를 껐다 켜면 버퍼 위에 모든 데이터가 사라지게 됩니다. 따라서 DBMS에 어떤 장애가 발생해서 프로세스 다운이 일어나면(즉, 서버가 죽으면) 메모리 위에 있는 모든 데이터가 날아갑니다.
결국 미래에 메모리 가격이 비싸진다고 해도 영속성이 보장되지 않는 경우 디스크를 완전하게 대체하는 것은 불가능합니다.
휘발성의 문제점
휘발성의 가장 큰 문제점은 장애가 발생했을 때 메모리에 있던 데이터가 모두 사라져버려 데이터의 부정합을 발생시키는 것입니다.
만약, 로그 버퍼 위에 존재하는 데이터가 디스크의 로그 파일에 반영되기 전에 장애가 발생해서 사라져버리면 큰 문제가 발생할 것입니다.
예를 들어, 은행 입출금 또는 카드 인출 같은 작업을 할 때 로그 버퍼에 장애가 발생할 경우 데이터베이스에 반영이 안되는 상황이 발생할 수 있습니다.
이렇게 로그 파일에 전달된 갱신 정보가 DBMS가 다운될 때 사라지는 현상은 DBMS가 갱신을 비동기로 하는 이상 발생할 수 밖에 없는 문제입니다.
DBMS에서는 이를 해결하고자 커밋 시점에 반드시 갱신 정보를 로그 파일(영속적인 저장소에 있는)에 작성합니다.
즉, 커밋 시점에서는 반드시 디스크에 동기 접근이 발생하게 되고 결국 여기서 지연이 발생할 가능성이 있습니다.
여기서 트레이드오프가 발생하게 되는데 디스크에 동기처리를 할 경우 데이터 정합성은 높아지지만 성능이 낮아지고, 성능을 높이려고 비동기 처리를 할 경우 데이터 정합성이 낮아집니다.
시스템 특성에 따른 트레이드 오프
Oracle, PostgreSQL, MySQL 등 대표적인 DBMS에서 데이터캐시와 로그 버퍼를 비교해보면 3개의 DBMS에서 공통으로 데이터 캐시에 비해 로그 버퍼의 초깃값이 굉장히 작다는 것을 알 수 있습니다.
데이터베이스가 서로다른 버퍼에 대해 극단적인 비대칭 크기를 가지게 한 이유는 데이터베이스가 검색을 주로 처리한다고 가정하기 때문입니다.
검색같은 경우 검색 대상 레코드가 수백만에서 수천만에 달하는 경우도 있지만 갱신처리 같은 경우 보통 검색에 비해 적은 양을 처리합니다.
따라서 갱신처리에 값 비싼 메모리를 많이 사용하는 것보다는 자주 검색하는 데이터를 캐시에 올려놓는 것으로 결정한 것입니다.
실제로 많은 DBMS에서 물리 메모리에 여유가 있다면 데이터 캐시를 되도록 많이 할당하는 것을 추천하고 있습니다.
물론, 검색에 비해 갱신이 자주 일어나는 데이터베이스라면 로그 버퍼의 크기를 늘리는 것이 성능 상 더 좋을 수 있습니다.
검색과 갱신 중에서 중요한 것
검색과 갱신에 대해서 빠른 속도를 보장하면 좋지만 물리 메모리 자원은 한정되어 있기 때문에 둘다 빠른 속도를 보장하는 것은 어렵습니다.
따라서 어떤 것을 우선시 할지에 대해 충분히 고민해야 합니다.
현대의 DBMS는 리소스를 자동으로 조정하여 상황에 맞게 메모리 할당을 하는 기능을 지원하기도 합니다. 단, 모든 설정을 자동 설정으로 의존하는 것은 위험합니다.
갱신 처리가 우선 되는 상황에서는 로그 버퍼의 크기를 키우는 것이 좋을 것이고, 검색 처리가 우선 되는 상황이라면 데이터 캐시의 크기를 키우는 것이 좋을 것입니다.
추가적인 메모리 영역 “워킹 메모리”
워킹 메모리란
DBMS는 로그 버퍼와 데이터 캐시 이외에도 일반적으로 메모리 영역을 하나 더 가지고 있습니다.
워킹 메모리라고 불리는 이 영역은 정렬 또는 해시 관련 처리에 사용되는 작업용 영역으로 사용됩니다.
정렬은 ORDER BY 구, 집합 연산, 윈도우 함수 등의 기능을 사용할 때 실행되며, 반면 해시는 주로 테이블 등의 결합에서 해시 결합이 사용되는 때 실행됩니다.
해시는 주로 테이블 등의 결합에서 해시 결합이 사용될 때 사용됩니다.
이 메모리 영역의 이름과 관리 방법은 DBMS에 따라 다릅니다.
이 작업용 메모리 영역은 SQL에서 정렬 또는 해시가 필요한 때 사용되고 종료되면 해제되는 임시 영역으로, 일반적으로는 데이터 캐시와 로그 버퍼와는 다른 영역으로 관리되는 경우가 많습니다.
이 영역이 성능적으로 중요한 이유는, 만약 이 영역이 다루려는 데이터 양 보다 작아 부족해지는 경우가 생기면 대부분의 DBMS가 스왑 메모리를 사용하게 됩니다.
많은 DBMS는 워킹 메모리가 부족할 때 사용하는 임시적인 영역을 가지고 있습니다.
해당 영역은 저장소 위에 존재하기 때문에 메모리에 비해 접근 속도가 느릴 수 밖에 없습니다.
- 오라클 : 임시 테이블 스페이스(TEMP Tablespace)
- SQL Server : TEMPDB
- PostgreSQL : 일시 영역(pgsql_tmp)
스왑 메모리
스왑 메모리란, 실제 메모리 램이 가득 찼지만 더 많은 메모리가 필요할 때 디스크 공간을 이용하여 부족한 메모리를 대체할 수 있는 공간을 의미합니다.
DBMS는 실제 메모리가 부족할 경우 스왑 메모리를 사용하게 되는데 앞서 설명했듯이 디스크는 메모리라는 저장 장치보다 속도가 느리다는 단점이 있습니다.
하지만, 메모리가 부족하다고 처리를 멈추거나 에러를 발생시키고 강제 종료된다면 심각한 문제를 야기할 수 있습니다.
스왑 메모리를 사용하면 메모리가 부족해지는 순간에 속도가 느려지는 변화가 발생할 수 있지만 계속해서 처리를 진행할 수 있게 됩니다.
또한 워킹 메모리의 경우 여러 SQL 구문들이 공유해서 사용하므로 하나의 SQL 구문을 실행하고 있을 때는 메모리에 잘 들어가지만 여러 개의 SQL 구문이 동시에 실행되면 메모리가 넘칠 수 있습니다.
따라서 그러한 상황을 재현할 수 있는 검사를 실시하지 않으면 메모리 부족 현상이 일어날지 판별하기 힘듭니다.
하나의 명령이 있는 것이 아닌 여러 명령이 존재할 경우 예측하기 더욱 어려워지기 때문입니다.
DBMS는 메모리가 부족할 경우 스왑 메모리를 통한 메모리 확보를 위해 작업 처리를 계속할 수 있도록 보장하려고 노력합니다.
이는 중요한 데이터를 보관하는 공간인 만큼 중간에 오류로 인해 요청한 작업을 완료할 수 있도록 보장하기 위해서입니다.
정리
- 기억장치는 1차에서 3차 기억장치 까지 존재하며 1차 기억장치의 경우 빠른 처리 속도를 가지지만 비용이 비싸 많은 저장공간을 가지기 힘들고 내려갈수록(2차, 3차) 처리 속도는 떨어지지만 비용이 낮아져 많은 저장공간을 가집니다.
- DBMS는 데이터의 영구적인 저장에는 디스크를 많이 사용하고 데이터를 임시 저장하고 처리하는 공간으로 메모리를 사용합니다.
- 데이터 캐시는 디스크에 있는 데이터의 일부를 메모리에 유지하기 위해 사용하는 메모리 영역으로, 빠른 데이터 조회를 위해 사용됩니다.
- 로그 버퍼는 갱신처리에 사용되는 메모리 영역으로 SQL 명령 후 로그 버퍼에 변경사항을 적용 후 커밋시점에 저장소에 적용됩니다.
- 일반적으로 데이터베이스는 갱신처리보다는 조회가 많이 일어나기 때문에 데이터 캐시가 더 많은 영역을 사용합니다.
- 워킹 메모리는 정렬 또는 해시 관련 처리에 사용되는 작업용 영역으로 사용됩니다.
- DBMS에서 작업을 처리할 때 메모리가 부족하다면 스왑 메모리를 통해 작업을 계속해서 처리합니다.
- 스왑 메모리란 실제 메모리 램이 가득 찼지만 더 많은 메모리가 필요할 때 디스크 공간을 이용하여 부족한 메모리를 대체할 수 있는 공간을 의미합니다.
'CS > DataBase' 카테고리의 다른 글
DBMS의 실행계획 확인하기 (1) | 2022.10.23 |
---|---|
DBMS와 실행 계획 (0) | 2022.10.22 |
DBMS 아키텍처 개요 (0) | 2022.10.16 |
데이터베이스 첫걸음 정리 - 36장. 트랜잭션 (0) | 2022.10.09 |
데이터베이스 첫걸음 정리 - 35장. 정규화 (0) | 2022.10.07 |