DB System Concepts 7th

[DB] 13-7. 메인 메모리 DB의 저장구조

patrick-star 2023. 8. 18. 08:39
728x90

오늘날의 main memory는 크기가 충분히 크고 가격도 저렴해서 많은 곳의 전체 DB가 메모리에 들어갈 수 있다.
이렇게 큰 main memory는 DB 버퍼에 많은 양의 메모리를 할당해서 사용할 수 있다.
그러면, 전체 DB를 버퍼에 적재할 수 있게 되면서 데이터를 읽기 위한 디스크 I/O 연산을 피할 수 있다. (다만, 블록을 갱신했다면 그 블록을 디스크에 작성(write)하는 작업은 필요하다)

따라서, 이와 같이 main memory가 큰 환경은 DB 일부만 버퍼에 저장되어 있는 환경보다 훨씬 더 좋은 성능을 제공할 수 있다.

메인 메모리 DB는 모든 데이터가 메모리에 존재하는 DB다. 메인 메모리 DB 시스템은 일반적으로 이 사실을 활용하여 성능을 최적화하도록 설계되었다. 특히, 버퍼 관리자를 완전히 없애 버렸다.

ex) 레코드 포인터가 주어졌을 때 레코드에 접근하는 비용

  • 디스크 기반의 DB
    레코드가 블록에 저장되고 레코드에 대한 포인터는 블록 식별자와 블록 내의 offset 또는 slot 번호로 구성된다.
    레코드에 대한 포인터를 따라가려면 블록이 buffer에 있는지 확인하고 buffer에 블록이 있다면 버퍼에서 위치를 찾아내고
    buffer에 블록이 없다면 가져와야 한다.

이러한 모든 작업은 상당한 수의 CPU 사이클을 필요로 한다.

  • 메인 메모리 DB

레코드가 이동하지 않는 한 레코드에 대한 직접 포인터(direct pointer)를 메모리에 저장할 수 있고 레코드에 접근하는 건 매우 효율적인 in-memory 포인터 순회가 된다.

블록 내의 슬롯 페이지 구조(slotted-page 구조) ⇒ 사용하지 않음

블록 내의 슬롯 페이지 구조로 레코드를 저장하면 다른 레코드를 삭제하거나 크기를 조정할 때 레코드를 블록 내에서 이동시킬수 있다. 이 경우에 레코드에 대한 직접 포인터는 더 이상 이용할 수 없고 slot page의 header에 있는 entry를 통해서 블록 내에 있는레코드에 접근해야 한다. 다른 프로세스가 데이터를 읽는 동안 레코드를 이동시키지 않으려면 해당 블록을 잠가야 한다.

이러한 overhead 때문에 메인 메모리 DB에서는 이 구조를 사용하지 않는다.

대신 메인 메모리에 직접 레코드를 할당하고 다른 레코드에 대한 갱신때문에 레코드를 이동하지 않도록 한다.
이러면 블록에 대한 잠금을 획득하지 않고도 원하는 동작을 수행할 수 있다.
하지만, 레코드를 직접 할당할 때 가변 크기의 레코드를 반복적으로 삽입 & 삭제하면 메모리가 단편화될 수 있다.

그래서, 메인 메모리 DB는 적절히 설계한 메모리 관리 방식을 사용하거나 주기적으로 메모리 압축을 수행해서 단편화되지 않도록 해야 한다.

메인 메모리에서 Column-Oriented storage를 사용하는 경우

column의 모든 값을 연속적인 메모리 위치에 저장할 수 있다.
그러나, relation에 대한 데이터 추가가 있다면 연속적인 할당을 보장하기 위해 기존 데이터를 재할당해야 한다.

이러한 overhead를 방지하기 위해 column의 논리적 배열여러 개의 물리적 배열로 나눌 수 있다.
간접 테이블(indirection table)은 모든 물리적 배열에 대한 포인터를 저장한다. (아래 그림으로 나타나 있음)

ex) 논리 배열의 i번째 요소를 찾고 싶다.

1) 간접 테이블을 사용해서 i번째 요소를 포함한 물리적 배열을 찾는다.
2) 적절한 offset을 계산해서 해당 물리적 배열 내에서 데이터를 조회한다.

메인 메모리 DB를 최적화하는 다른 방법은 이후의 장에서 살펴본다.