537. 시계열 DB 롤업(Rollup)과 다운샘플링 쿼리 효율화

⚠️ 이 문서는 "1초마다 찍히는 1년 치 센서 데이터(3천만 건)를 몽땅 가져와서 모니터에 한 방에 띄워줘!"라는 미친 요구사항 앞에서 브라우저와 DB가 동시에 뻗어버리는 것을 막기 위해, **데이터의 해상도를 1시간, 1일 단위로 실시간 압축하여 화면에 뿌려주는 시계열 DB의 '다운샘플링 쿼리'**를 다룹니다.

(※ 515번 문서에서 '자동 삭제' 관점의 보존 정책을 다루었으며, 이 문서는 '쿼리 성능 최적화' 관점의 롤업(Rollup) 및 지속적 쿼리(Continuous Query) 메커니즘을 심화로 다룹니다.)

핵심 인사이트 (3줄 요약)

  1. 본질: 시계열 데이터베이스(TSDB)에서 엄청나게 많은 양의 촘촘한(High-resolution) 원본 데이터를, GROUP BY time(1h) 같은 시간 단위를 기준으로 묶어 요약된 평균/최댓값(Low-resolution)으로 실시간 변환하는 쿼리 기술이다.
  2. 해결하는 문제: 모니터의 픽셀 수는 1,920개밖에 안 되는데, 그 안에 100만 개의 점을 그리려고 DB에서 데이터를 퍼오는 네트워크 대역폭 낭비와 브라우저의 렌더링 폭발을 막아준다.
  3. 구현 기술 (Continuous Query): 유저가 쿼리를 날릴 때마다 1억 건을 묶으려면 서버가 죽으므로, DB 엔진이 백그라운드에서 매시간 미리미리 계산해서 별도의 **요약 테이블(Rollup Table)**에 몰래 적어두는 자동화 기술이 필수로 동반된다.

Ⅰ. 개요: 보이지 않는 점들을 그리지 마라 (Context & Necessity)

서버 CPU 모니터링 대시보드(Grafana)를 열었다.

  • 어제 하루 치 데이터(86,400초)를 볼 때는 1초 단위로 그래프가 촘촘하게 움직인다. (원본 데이터)
  • 범위를 **'지난 1년 치'**로 늘렸다.

만약 DB가 1년 치 원본 데이터(3,153만 건)를 JSON으로 보내준다면 어떻게 될까? 기가비트 랜선이라도 다운받는 데 한참이 걸릴 것이고, 크롬 브라우저는 메모리가 터져서 앗, 이런! 에러를 띄우며 죽어버릴 것이다. 애초에 인간의 눈이나 모니터 해상도로는 3,153만 개의 점을 구별할 수도 없다.

그래서 그라파나는 뒤에 있는 TSDB(InfluxDB 등)에 이렇게 쿼리를 날린다. "야! 1년 치 데이터를 줄 때는 1초 단위로 주지 말고, 하루(1d) 치를 하나로 뭉쳐서(평균 내서) 딱 365개의 점으로만 롤업(Rollup)해서 보내!"

📢 섹션 요약 비유: 다운샘플링은 **'모자이크 처리'**와 같습니다. 가까이서 볼 때는 10만 개의 퍼즐 조각(원본 데이터)이 다 필요하지만, 아주 멀리서 그림 전체(1년 치 트렌드)를 볼 때는 100개의 커다란 색종이(롤업 데이터)만 대충 붙여놔도 그림을 이해하는 데 아무런 지장이 없으며, 심지어 눈이 훨씬 편안합니다.


Ⅱ. 롤업(Rollup) 쿼리의 수학적 메커니즘 ★

시계열 DB에서 롤업을 하려면 3가지 요소가 반드시 쿼리 안에 들어가야 한다.

1. 집계 함수 (Aggregation Function)

  • 수천 개의 점을 1개로 뭉칠 때 대표값을 무엇으로 할 것인가?
  • 평균(MEAN), 최댓값(MAX), 최솟값(MIN), 합계(SUM) 등을 쓴다. (주로 트렌드를 보기 위해 MEAN이나 피크를 잡기 위해 MAX를 많이 쓴다.)

2. 시간 단위 그룹핑 (Time Bucket)

  • "몇 초(분, 시간) 단위로 뭉칠 것인가?"
  • GROUP BY time(1h) (1시간 단위 롤업), GROUP BY time(1d) (하루 단위 롤업)

3. 빈칸 채우기 (Fill / Interpolation)

  • 1시간 단위로 뭉치는데, 하필 그 1시간 동안 센서가 고장 나서 들어온 데이터가 0건이라면?
  • DB는 그 시간을 NULL로 비워둘지, 0으로 채울지(fill(0)), 아니면 앞시간의 데이터를 끌어올지(fill(previous) - 375번 문서)를 결정해 주어야 그래프가 중간에 끊어지지 않는다.

Ⅲ. 실무 아키텍처: 지속적 쿼리 (CQ)와 요약 테이블

사용자가 대시보드를 열 때마다 10억 건의 데이터를 GROUP BY time(1h) 한다고 치자. 당연히 DB CPU가 버티지 못한다. 고수들은 **요약 테이블(Rollup Table)**을 미리 만들어둔다.

  • Continuous Query (CQ / 지속적 쿼리)
    • InfluxDB 같은 TSDB에 존재하는 내장 스케줄러다.
    • "DB야! 매 정각마다 지난 1시간 치 원본 데이터를 AVG() 돌려서, 그 1개의 결괏값을 cpu_hourly_rollup이라는 테이블에 자동으로 INSERT 해둬!"라고 예약해 두는 기능이다.
  • 결과: 사용자가 1년 치 통계를 볼 때는 원본 테이블을 아예 건드리지 않고, 이미 1시간 단위로 예쁘게 압축되어있는 cpu_hourly_rollup 테이블(365일 = 8,760줄)만 순식간에 읽어온다.
┌──────────────────────────────────────────────────────────────┐
│           시계열 DB의 롤업(Rollup) 쿼리 자동화 파이프라인 시각화         │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│ [ 🌊 원본 테이블 (1초 단위) ] ──▶ 최근 7일 치만 저장 (이후 삭제)       │
│   10:00:01 (30도)                                              │
│   10:00:02 (35도)                                              │
│   ... (3,600건)                                               │
│                                                              │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ ⚙️ Continuous Query (매시간 자동으로 도는 롤업 엔진)          │ │
│ │  SELECT MAX(온도) INTO 요약_테이블 FROM 원본 GROUP BY time(1h) │ │
│ └──────────────────────────────────────────────────────────┘ │
│         │ (압축)                                              │
│         ▼                                                    │
│ [ 📊 요약 테이블 (1시간 단위) ] ──▶ 평생 보관! (장기 트렌드 분석용)     │
│   10:00:00 (최고 35도)   ◀── 딱 1줄로 압축됨!                       │
│   11:00:00 (최고 38도)                                         │
└──────────────────────────────────────────────────────────────┘

Ⅳ. 결론

"보지 못하는 데이터는 보내지도 말고, 쿼리하지도 마라." 데이터 파이프라인과 대시보드를 설계할 때 시니어 엔지니어가 가장 집착하는 것이 바로 이 다운샘플링(Downsampling)과 롤업 전략이다. 프론트엔드가 수십 MB의 JSON을 받아 브라우저를 다운시키는 참사를 막으려면, 백엔드(DB) 단에서 시간의 축을 압축하여 꼭 필요한 해상도의 데이터만 렌더링하도록 쿼리 구조를 방어해야 한다. 이는 단순히 스토리지 비용을 아끼는(515번 문서) 행위가 아니라, 시계열 시스템 전체의 조회 성능(Latency)을 100배 이상 끌어올리는 가장 강력하고 본질적인 아키텍처 패턴이다.


📌 관련 개념 맵

  • 관련 시스템: InfluxDB, Prometheus, Grafana
  • 기반 철학: Retention Policy (보존 정책 - 최신 원본은 지우고 롤업 테이블만 남기는 기술, 515번 문서)
  • 관련 연산: Interpolation (보간법 - 빈칸 채우기, 375번 문서)
  • 대칭 개념: RDBMS의 구체화된 뷰 (Materialized View - 쿼리 결과를 미리 디스크에 저장해 두는 기술)

👶 어린이를 위한 3줄 비유 설명

  1. 1년 동안 매일매일 적은 '그림일기장' 365장을 한 번에 다 읽으려면 며칠이 걸리겠죠? (풀 스캔)
  2. 다운샘플링은 "1월에는 눈이 왔고, 8월에는 바다에 갔어"라고 한 달의 이야기를 딱 한 줄로 뭉뚱그려서(롤업) 요약하는 거예요.
  3. 그리고 그 12줄짜리 요약본을 맨 앞장에 미리 적어두면(지속적 쿼리), 나중에 "작년에 뭐 했지?" 궁금할 때 일기장 전체를 안 읽고 맨 앞장 1페이지만 보면 1초 만에 알 수 있답니다!