최근 TimescaleDB에 실시간 센서 데이터를 적재하는 과정에서 몇 가지 오류를 경험하였습니다. 로그를 분석하고 해결 방법을 찾아가는 과정을 정리해봅니다.
1. 문제 상황
Kafka에서 수집한 수천 개의 센서 데이터를 TimescaleDB에 적재하는 컨테이너 로그에서 다음과 같은 오류가 반복적으로 발생했습니다.
1.1 statement_timeout
오류
ERROR: canceling statement due to statement timeout
이는 PostgreSQL의 statement_timeout
값(쿼리 실행 최대 시간)을 초과하면 발생하는 에러입니다. 대량 데이터를 한 번에 Insert하거나, 인덱스 부재, 네트워크 지연, 병렬 쓰기 병목 등으로 실행 시간이 길어질 경우 나타납니다.
1.2 row is too big
오류
ERROR: row is too big: size 9504, maximum size 8191
PostgreSQL에서는 단일 row가 8KB(8191 bytes)를 넘을 수 없습니다. double precision
, integer
, timestamp
같은 고정형 타입은 TOAST(외부 저장)가 불가능하므로, 컬럼 수가 많아지면 이 제한을 쉽게 초과합니다. 실제 환경에서는 약 1182개의 컬럼이 존재했는데, 이는 제한을 훨씬 넘는 구조였습니다.
2. 원인 분석
- statement_timeout
- 쿼리 실행 시간이 길어지면 PostgreSQL이 강제로 중단
- Kafka batch 처리량이 많거나 Connection Pool 병목 시 자주 발생
- row size 초과
- 8KB 페이지 제한으로 인해 고정형 타입 컬럼이 너무 많으면 단일 row에 저장 불가
double precision
기준으로 약 1015개가 최대치- 안정성을 위해 800~900개 이하로 제한하는 것이 권장됨
3. 해결 방법
3.1 statement_timeout
해결
- PostgreSQL 세션에서 설정
SET statement_timeout = '2min';
- JDBC URL 설정
jdbc:postgresql://host:5432/db?statement_timeout=120000
- Spring Boot 설정
spring: datasource: url: jdbc:postgresql://host:5432/db?statement_timeout=120000 hikari: maximum-pool-size: 10
- Kafka Consumer 설정 조정
max.poll.records
값 축소, batch 크기 조절, 병렬성(concurrency) 적정화
3.2 row is too big
해결
- Long Format(세로형) 스키마로 변경 → 컬럼 수는 4개로 고정, row size 문제 해소
| device_id | timestamp | parameter_name | value |
|-----------|---------------------|----------------|--------|
| A | 2025-08-05 15:00:00 | temp | 22.5 |
| A | 2025-08-05 15:00:00 | pressure | 1013.2 |
- 파라미터 그룹별 테이블 분할
- 예:
sensor_temperature
,sensor_pressure
등 그룹별로 나누어 저장
- 예:
- JSONB로 묶어서 저장
- row size 제한을 피할 수 있지만, 쿼리 성능 및 TimescaleDB 기능 사용이 제한됨
4. 컬럼 수 제한 정리
데이터 타입 | 이론상 최대 컬럼 수 | 안정적 사용 권장 수 |
---|---|---|
double precision | 약 1015 | 800~900 |
integer | 약 1500 | 1200 이하 |
boolean | 최대 1600 | 1400 이하 |
5. 결론
statement_timeout
문제는 쿼리 최적화, 배치 크기 조정, 타임아웃 설정 증가로 해결 가능row size 초과
문제는 데이터 모델 변경이 필수
특히 시계열 데이터는 wide table 구조보다 long format 구조가 TimescaleDB의 성능과 기능을 최대한 활용할 수 있음- PostgreSQL의 row size 제한(8KB)은 설정 변경 불가이므로, 데이터 구조 설계 시 이를 반드시 고려해야 함
반응형
'개발 (Development) > PostgreSQL' 카테고리의 다른 글
[PostgreSQL/Java] shared memory 에러 해결: Java + MyBatis 대용량 쿼리 처리 (0) | 2025.08.25 |
---|---|
[PostgreSQL] View와 Materialized View의 차이점과 사용법 (0) | 2025.08.03 |
[PostgreSQL] 문자열을 timestamp with time zone으로 변환하는 방법 (0) | 2025.07.27 |
[PostgreSQL] MyBatis foreach + UNION ALL 쿼리의 성능 문제와 PostgreSQL 최적화 (1) | 2025.07.05 |
[PostgreSQL] PostgreSQL에서 threshold 값 이력 관리 및 최신값 조회 테이블 설계하기 (0) | 2025.06.28 |