강의에서 항상 중요하게 생각하는 부분은 Disk에서부터 Memory로 데이터를 fetching하는 상황을 최소화 하는 것이다. 앞서서 배운 여러 기법들은 fixed-length storage, slotted storage 와 log-structured storage와 같이 tuple level에서 어떻게 데이터를 저장할 것인가에 대해서 배웠다.

storage의 종류
  • fixed-length storage : tuple의 길이가 고정되어있을 때 사용하는게 좋고 무조건 차곡차곡 쌓아간다.
  • slotted storage : tuple의 길이가 가변적인 때도 사용할 수 있고 block 내부에 낮은 주소값에 page정보를 가지는 header를 가지고 pointer를 저장하며 뒤쪽에서부터 tuple을 저장한다.
  • log-structured storage : 앞에 2개의 storage는 모두 데이터를 필연적으로 fetching해야한다. 하지만 데이터의 변화를 기록한 부분만을 가지고 있다면 데이터를 조금 더 쉽게 읽을 수 있을 것이다.

어떤 구조가 더 낫다는 말은 할 수 없다. 다만 각 저장 방법에 장단점이 존재하므로 이를 알고 써야한다는 점이다.

이번 장에서는 저장의 관점이 아니라 Execution 실행의 관점에서 어떤 형식이 좋을지 좀 더 생각해 본다.

OLAP vs OLTP

우리가 보통 DBMS를 사용하는데 있어서 여러가지 이유로 쓸 수 있지만 크게 2가지로 나눠 볼 수 있다.

  • 어떤 데이터를 CURD의 관점에서 작업한다는 것
    • tuple에 대한 지속적인 작업이 진행되는 것
    • 예를 들어 유저가 로그인을 하는 경우에 Read작업이 빈번하게 일어날 수 있다는 것이다.
  • 여러 데이터를 집계하는 관점에서 작업한다는 것
    • 이러한 작업은 여러 tuple을 훑고 이를 통해서 어떤 결과 값을 얻는 것
    • 예를 들면 특정 날짜에 접속한 모든 사람을 집계하는 경우 aggregate function이 사용될 것이다. 이런 상황을 용어로 아래와 같이 표현한다.

OLAP : OnLine Analyitcal Processing OLTP : OnLine Transaction Processing

OLAP

문자 그대로 여러데이터를 분석하는 관점에서 데이터베이스를 구성한다. 분석을 한다는 것은 많은 데이터를 읽다는다라는데 좋은 성능을 필요로 함으로 Read-Heavy작업에 굉장한 강점을 보이고 집계란 본질적으로 복잡한 작업을 포함하므로Complex한 쿼리에 강점이 존재한다.

OLTP

Transaction이 붙은 걸로보아 데이터베이스의 근본적인 저장하고 수정 및 삭제와 같은 작은 tuple에 대한 빈번한 작업을 효율적으로 하는데 강점이 있다. 이러한 이유로 Write-Heavy한 작업에 굉장한 강점이 존재하고 Simple한 작업에 강점이 존재한다.

NSM / DSM / PAX

OLAP와 OLTP모두 어떤 추상적인 개념이라고 생각한다. 딱히 구현을 어떻게 해야한다는 것들이 존재하지 않기 때문이다. 이러한 추상적인 개념을 구현한 부분이 NSM / DSM / PAX이다.

NSM

N-ary Storage Model라고 불리우며 row storage라고 불린다. 기본적으로 tuple을 한 page안에 저장한다. 이로인해 page를 한번 load하면 근처에 존재하는 모든 tuple을 읽을 수 있다.

이러한 이유로 트랜잭션처리가 빠르고 이로인해 OLTP시스템에서 많이 사용된다. 단점은 대량의 데이터를 조회해야하는 경우에는 필요없는 많은 데이터를 fetching하게 된다.

DSM

Decomposition Storage Model라고 불리우며 column storage라고 불린다. 이름에서도 알 수 있듯이 분해를 해서 저장을 한다는 개념을 가진다. 모든 tuple을 column을 따라서 page에 넣는다. 따라서 NSM처럼 필요없는 데이터를 fetching할 필요가 없고 특정 column의 값을 가져올 때 상당히 유리하다.

이때 각기 다른 page에 존재하는 순서를 구분하기 위해서 2가지 방법이 있을 수 있는데

  1. fixed-length Offset : 각 page의 순서를 같게 유지 하면서 데이터를 저장
  2. Embeded Ids : 각 tuple마다 데이터의 id를 저장

높은 locality를 가지고 데이터를 접근하는 부분이 유리하다.

하지만 인간은 이러한 2개의 이점을 모두 챙겨하고 싶어한다. 그래서 PAX가 등장한다.

PAX

Partition Attributes Across라고 불리는 NSM과 DSM의 하이브리드 버젼이라고 생각하면 된다. 혹시 parquet이라고 들어본적이 있나?

필자는 과거에 kaggle을 하면서 ubiquent competition을 진행하면서 사용해 본적이있다. 분명 csv인데 용량이 5gb인지 10gb인지 기억은 안나지만 텍스트 문서로는 굉장히 큰 상황이었다. 이때 pd.read_csv()로 하면 아예 메모리에 올라오지도 않는 문제가 있었는데, 이를 parquet으로 해결한적이 있다.

다시 pax로 돌아와서 이는 한 page에 일정 row그룹을 만들어서 이를 column을 기준으로 다시 정리해 놓은 구조를 가진다. (그림은 추후첨부)

Compression

Why?

앞서서 OLTP와 OLAP를 배우고 NSM / DSM / PAX를 배우면서 어떤 시스템을 사용할지 그리고 이를 어떤 형식으로 구현해 볼지를 고민해 봤다.

하지만 근본적으로 데이터가 매우 많은 경우를 생각해보면 위에서 배운게 도움이 안될 수 도 있다. 직관적으로 그냥 데이터를 작게 하고 싶을 수도 있다.

좀 더 꿈을 꿔보면 Compression 된 상태로 데이터를 읽고 쓰면 좋겠다 라고 생각할 수 있다. 이런 방법을 또 만들어내는 인간들이 컴퓨터 과학자인 것 같다.

Trade-off in speed vs compression

그럼 압축이 좋다는 건 이해했는데, 압축하면 반대로 압축을 풀어야 읽을 수 있지 않나? 결국 이러한 상황도 압축을 하고 저장했다가 꺼내서 압축을 푼다음에 읽는 상황이 그냥 저장하는 상황보다 더 빨라야 효용성이 있다는 것이다.