로코
February 7, 2026

시계열 DB에 대해 알아보자

발행일 February 7, 2026  •  6분 소요  • 1091 단어  • 다른 언어 선택:  English, 日本語
Table of contents

대규모 아키텍처를 설계하거나, 분산형 시스템을 구축하려고 할 때 Time Series Database(TSDB) 도입을 고려해볼 수 있다. 오늘은 TSDB가 어떤 도구인지, 어떤 특징들을 가지고 있으며, 또 어떤 문제들을 해결하는 데 도움을 주는지를 알아보고자 한다.

1. 시계열 데이터란?

TSDB는 시계열 데이터를 저장하고 처리하는 데이터베이스이다. 그렇다면 시계열 데이터란 무엇인가? 시계열 데이터는 단순히 타임스탬프가 달려 있는 데이터가 아니다. 더 정확하게는 “시간에 따라 추적, 모니터링, 다운샘플링, 집계되는 측정값 또는 이벤트” 라고 정의할 수 있으며, 여기서 말하는 측정값 또는 이벤트에는 아래와 같은 것들이 포함될 수 있다.

이러한 데이터들을 다루는 시계열 데이터는 일반적인 DB와는 다르게 아래와 같은 차별점들을 가진다.

이러한 특성들을 다루기 위해 TSDB가 어떤 전략들을 취하는지 알아보자.

2. 쓰기 최적화

일반적인 DB의 경우 데이터를 쓰려면 쓰기 위한 위치를 찾고 수정하거나 삽입하는 작업을 수행해야 할 것이다. 아래와 같은 형태로 작업이 진행될 것이다.

[Seek to block 4752][Read][Modify][Write][Seek to block 9201] → ...

반면에 TSDB는 기존 데이터를 수정할 필요가 없고, 시간순으로 데이터를 적재하면 되므로 Append-only 방식으로 데이터를 추가하기만 하면 된다. 아래와 같이 작업들이 훨씬 단순화될 것이다.

[Write to end][Write to end][Write to end] → ...

LSM(Log-Structured Merge) 트리

LSM 트리는 InfluxDB, Cassandra, LevelDB 등 고성능의 쓰기 처리량을 자랑하는 데이터베이스 시스템의 특제 비법 소스다. LSM 트리의 핵심 아이디어는 다음과 같다.

그리고 LSM 트리의 작동 방식은 아래와 같다.

  1. 최신 데이터는 Memtable 메모리 버퍼에 저장

데이터는 키 순서대로 정렬을 유지한다. 이 때 쓰기 작업은 RAM에 접근하므로 속도가 매우 빠르다.

  1. SSTable(Sorted String Table) 디스크에 플러시

Memtable이 가득 차면 변경 불가능하며 정렬된 SSTable 파일로 저장된다. Memtable은 이미 정렬되어 있으므로 이 플러시 작업은 순차적으로 간단하고 빠르게 완료될 수 있다. 또한 플러시 작업 이후에는 Memtable을 비워주고 초기화한다.

  1. 백그라운드 압축

백그라운드에서는 작은 SSTable을 더 큰 SSTable로 병합하는 작업을 수행한다. 또한 중복 항목들과 툼스톤(삭제 대상 마크)을 제거하기도 한다.

이러한 LSM 트리의 작동 방식으로 인해 쓰기 작업은 읽기 작업을 방해하지 않게 된다. Memtable은 항상 최신 데이터를 처리하고 백그라운드에서 기존 데이터들을 정리하게 함으로써, 지속적으로 높은 쓰기 처리량을 유지할 수 있다.

하지만 쿼리를 위해 여러 SSTable을 확인해야 하는 경우에는 읽기 성능 저하가 생길 수 있다. 또한 쓰기 증폭이 발생한 경우 압축 과정에서 데이터가 여러 번 재작성될 수 있다.

따라서 LSM 트리는 쓰기 작업량이 많고, 읽기 성능은 어느 정도 희생할 수 있을 때 활용하기 좋다.

3. 시간 기반 인덱싱 및 파티셔닝

시계열 데이터는 이미 타임스탬프 기반으로 정렬되어 삽입되므로 쓰기 작업에 인덱싱이 필요하지 않다. 그리고 시간 범위에 따라 파티셔닝을 하면 쓰기 작업 시 어느 파티션에 데이터를 저장할지 고민할 필요가 없어진다. 데이터 보존 작업 또한 오래된 파티션을 삭제하는 방식으로 간편하게 진행할 수 있다.

블록 레벨 메타데이터

TSDB에서 데이터 블록들 또한 타임스탬프 기반으로 정렬되어 있다. 따라서 시간 범위에 해당하지 않는 블록들은 체킹 없이 스킵할 수 있고, 이에 따라 쿼리 성능이 향상된다. 각 블록에는 시간에 대한 최소/최대 타임스탬프, 필요에 따라 최소/최대 값을 기록해둔다. 이러한 메타데이터는 시간 기반 파티셔닝과 함께 데이터 양이 많아지더라도 쿼리 성능을 유지할 수 있도록 돕는 필터 계층으로 작용한다.

4. 다운샘플링 및 압축

시계열 데이터는 특성상 덜 중요한 내용을 덜어내고 압축해서 표현하기에도 용이하다. 아니, 사실은 초당 수백만 개의 데이터 포인트가 지속적으로 인입된다는 TSDB의 특성상 다운샘플링 작업은 필수적이라고도 할 수 있다. TSDB에서 높은 정밀도를 가진 최신 데이터들은 집계 및 다운샘플링되어 장기 데이터로 변환된다. 일반적인 다운샘플링 및 리텐션 전략은 다음과 같다.

이와 같은 규칙들은 사용자가 직접 정의할 수 있으며, 이를 활용해서 저장 효율성 및 읽기 성능을 비약적으로 향상시킬 수 있다.

5. 압축 알고리즘

앞서 말했듯 TSDB의 핵심은 수많은 쓰기 연산을 메모리 버퍼에서 처리하는 것과, 백그라운드에서 압축하는 작업이라고 할 수 있다. 그렇다면 어떻게 압축하는 것일까? 그 부분에 대한 개념들을 알아보자.

델타 인코딩

Raw values:     [45.2] [45.3] [45.1] [45.4]
Delta encoded:  [45.2] [+0.1] [-0.2] [+0.3]

델타 인코딩은 원본 값에서 얼만큼 변했는지 변화량만 기록하도록 바꾸는 작업이다. 변화값은 원본 값보다는 작은 숫자이므로 값을 저장하는 데에 필요한 bit 수도 훨씬 적어진다.

델타 오브 델타 인코딩

Raw timestamps:     1000, 1010, 1020, 1030, 1040
Deltas:             10  , 10  , 10  , 10  , 10  , ...
Delta-of-deltas:    10  , 0   , 0   , 0   , 0   , ...

델타 오브 델타 인코딩은 더 나아가서 변화량에 대한 변화량을 기록하는 방식이다. 이는 타임스탬프 간격이 완전히 규칙적일 때 사용할 수 있는 방법이며, bit 수를 좀 더 줄여줄 수 있다.

XOR 압축

Value 1: 0 10000010 01101000101000111101011
Value 2: 0 10000010 01101000110000100000000
XOR:     0 00000000 00000000011000011101011
                    ^^^^^^^^^^ lots of leading zeros

XOR 압축은 연속된 float 기반 값들이 종종 유사한 값들을 가진다는 점을 활용하는 압축 알고리즘이다. 위와 같이 동일한 bit 부분을 모두 0으로 치환해서 전체 bit 수를 크게 줄일 수 있는 방식이다. 메타에서 개발한 고릴라 압축 기법도 여기에 해당한다.

Run-length 인코딩

Run-length 인코딩은 모니터링 지표와 같이 측정값이 반복해서 나타나는 경우에 해당 값을 카운트와 함께 하나로만 저장하는 방식이다. 로그인 횟수, 요청 수 등을 기록할 때 용이하다.

6. TSDB 선택 가이드

마지막으로 어떤 상황에서 어떤 TSDB를 활용하는 것이 좋을지 정리해보자.

InfluxDB

Prometheus

TimescaleDB

Kdb

Graphite

References

Contact me

email: nmin1124@gmail.com