GN⁺: TimescaleDB에 1조 개의 기상 데이터 로딩
(aliramadhan.me)날씨 데이터 웨어하우스 구축하기 파트 1: TimescaleDB에 1조 행의 날씨 데이터 로딩하기
우리가 하고 있는 일의 의미
날씨 데이터 웨어하우스를 구축하는 이유
- 기후 변화의 징후를 분석하기 위해 전 세계의 과거 날씨 데이터를 모아 분석하는 것이 좋겠다고 생각함
- 대규모 날씨 데이터 웨어하우스가 있다면, 자카르타가 실제로 더 따뜻해졌거나 폭풍이 심해졌는지, 칠레가 전반적으로 더워지거나 구름이 많아지는지 등을 지역별로 파악할 수 있음
- 이를 통해 지구상 어느 지역이 가장 많은 기후 변화를 경험했는지, 어떤 종류의 변화가 있었는지 파악 가능
- 전 세계적으로 이런 분석을 하려면 데이터 웨어하우스 질의 속도를 높여야 하며, 데이터가 매우 많음
- 첫 단계는 데이터를 PostgreSQL에 로딩하는 것임. TimescaleDB로 시계열 쿼리 속도를 높이고, PostGIS로 지리공간 쿼리 속도를 높이는 것이 유망해 보임
데이터 소개
- 실제 관측 데이터가 아닌 ERA5 기후 재분석(climate reanalysis) 제품 데이터 사용
- ERA5는 관측 데이터로 제약을 받는 기후 모델 실행 결과로, 관측이 많은 곳은 관측과 유사하고 관측이 없는 곳은 물리적으로 일관되며 기후 통계와 일치
- ERA5는 1940년부터 전 지구를 0.25도 해상도로 시간당 데이터 제공. 기온, 강수량, 운량, 풍속 등 변수별로 7억 5천만 행 이상의 데이터
- 이 데이터를 관계형 DB에 빠르게 삽입하는 것은 쉽지 않음
데이터 삽입 방법
단일 행 insert 문
- 가장 간단한 방법이지만 매우 느림. 초당 3000건 삽입으로 전체 데이터 로딩에 약 8년 소요
- 구문 분석, 테이블/컬럼 검증, 실행 계획, 테이블 잠금, 버퍼 쓰기, 디스크 쓰기, 커밋 등 오버헤드가 큼
다중 값 insert
- 한 insert 문으로 여러 행 삽입. 네트워크, 구문 분석, 실행 계획 오버헤드 감소
- psycopg3가 초당 25,000~30,000건으로 가장 빠름
- 하지만 여전히 전체 데이터 로딩에 약 10개월 소요
copy 문
- 대량 데이터 로딩에 최적화된 방법. CSV나 바이너리 파일에서 직접 읽어서 구문 분석, 계획, WAL 사용 최적화
- 이미 CSV가 있다면 간단히 copy 문 사용 가능
- psycopg3의 copy는 초당 10만건 이상 삽입 가능. 오버헤드 포함해도 3개월 내 전체 데이터 로딩 가능
- copy로 장시간 고속 삽입 시 병목 현상 주의 필요
병렬 copy
- 여러 copy 작업을 병렬로 수행해 속도 향상
- 단일 테이블 삽입은 병렬화 효과가 크지 않아 16개 worker 이상은 성능 개선 없음
외부 도구 사용
- pg_bulkload와 timescaledb-parellel-copy 벤치마크
- pg_bulkload가 빠르지만 기본적으로 WAL을 건너뛰기 때문에 안전하지 않음
- timescaledb-parallel-copy는 다중 worker로 초당 30만건 이상 안전하게 삽입 가능
PostgreSQL 설정 조정
- fsync와 full_page_writes를 끄면 디스크 쓰기를 피해 더 빠르게 할 수 있으나 위험
- unlogged 테이블도 WAL을 사용하지 않아 빠르지만 크래시 시 잘림. hypertable은 unlogged가 될 수 없음
최상의 방법은?
- psycopg3로 직접 hypertable에 copy하는 것이 가장 좋음. CSV 파일은 timescaledb-parallel-copy 사용
- 병렬화는 12~16개 worker가 적당
- 규칙을 해제하면 초당 46만건까지 가능하지만 위험
- 하드웨어 업그레이드로 더 빠른 속도 가능
- ClickHouse가 더 빠를 수 있지만 PostgreSQL을 배우고 싶어서 TimescaleDB 선택
- 초당 46만건이면 20일 내 전체 데이터 로딩 가능
GN⁺의 의견
- ERA5 데이터를 관계형 DB에 넣어서 분석하려는 시도가 흥미롭네요. 기존에는 xarray나 dask로 NetCDF 데이터를 직접 분석하는 게 일반적이었는데, 데이터 웨어하우스를 구축하면 더 복잡한 질의를 수행할 수 있겠어요.
- 저자의 하드웨어 스펙이 5년 전 것인데도 초당 46만건을 넣을 수 있다는 점이 인상적이에요. 최신 하드웨어라면 초당 100만건도 가능할 거예요. 하지만 fsync와 full_page_writes를 끄는 것은 DB 무결성을 해칠 수 있으니 주의해야겠네요.
- PostgreSQL의 병렬 처리 기능이 단일 테이블에는 크게 도움이 안되는 것 같아요. 병렬 처리와 파티셔닝을 결합한다면 더 높은 성능을 낼 수 있을 거예요. Citus 같은 Postgres의 수평적 확장 솔루션도 고려해볼 만해요.
- 기후 변화 분석에 ERA5 데이터가 활용될 수 있다는 점이 흥미로워요. 관측 데이터가 부족한 지역의 과거 기후를 분석할 수 있겠네요. 하지만 ERA5는 어디까지나 모델 결과물이라는 한계가 있어요. 관측 데이터로 보정하긴 했지만, 불확실성이 있다는 점을 감안해야겠어요.
- 분석 플랫폼으로는 Snowflake나 BigQuery 같은 클라우드 데이터 웨어하우스를 쓰는 게 일반적이에요. 하지만 저자처럼 자체 하드웨어를 다루며 배우는 것도 의미가 크죠. 특히 기후 데이터는 용량이 크기 때문에 클라우드로 옮기는 게 쉽지 않아요. 앞으로 실제 분석 결과가 기대돼요.
Hacker News 의견
요약하면 다음과 같음:
-
지리공간 데이터 분석 시 좌표계(CRS)와 지도 투영법을 이해하는 것이 중요함. 대규모 지리공간 작업엔 Google BigQuery가 가장 뛰어남.
-
관계형 DB가 격자 기상 데이터에 적합한지는 실험을 통해 알아봐야 함.
-
Timescale에서 Hypertable이 느린 이유는 기본으로 생성되는 timestamp 컬럼 인덱스 때문일 수 있음.
create_default_indexes=>false
옵션으로 인덱스 생성을 건너뛰거나 데이터 입력 후 인덱스를 만드는 게 좋음. -
기상 데이터를 RDBMS로 옮기는 게 어떤 이점이 있는지 분석이 부족함. Serverless + 객체 스토리지로도 매우 빠른 응답 속도를 얻을 수 있음.
-
ERA5 같은 대부분의 기상/기후 데이터셋은 규칙적인 위경도 그리드로 구성되어 있어 구조를 완전히 파괴하는 건 좋지 않음. ARCO-ERA5 같이 클라우드에 최적화된 버전을 활용하는 게 나음.
-
PostgreSQL에서 WAL을 끄고
VACUUM FREEZE
명령을 주기적으로 실행하면 대량 데이터 로드 시 성능을 더 높일 수 있음. -
COPY를 사용할 수 없다면 행을 JSON 문자열로 인코딩해 단일 쿼리 파라미터로 보내고
json_to_recordset
을 사용하는 것도 좋은 방법임.