계층형 저장
오래된 창을 컬럼 지향 청크로 압축해 옆 테이블로 옮기고, SELECT 는 그것을 자동으로
합쳐 읽습니다. 애플리케이션은 데이터가 압축됐는지 알 필요가 없습니다.
쓰기 ──▶ [ 핫 구간 ] ── hot_window 경과 ──▶ [ 콜드 청크 ] ── cold_window 경과 ──▶ 삭제
행 저장 <테이블>__chunks
◀────── SELECT 이 알아서 합친다 ──────▶
설정
정책은 테이블 extensions 맵의 timeseries_tiering 키에 JSON 문자열로 넣습니다.
ALTER TABLE pp.tm_tag_point WITH extensions = {
'timeseries_tiering': '{"hot_window":"2d","chunk_window":"1d","cold_window":"3650d","interval":"1h"}'
};
| 키 | 필수 | 기본값 | 뜻 |
|---|---|---|---|
hot_window | 필수 | — | 이 나이보다 젊은 행은 건드리지 않음. chunk_window 이상이어야 함 |
chunk_window | 1h | 재인코딩 창의 길이. 청크 1개 = 태그 1개 × 창 1개 | |
cold_window | 없음 | 이보다 오래된 청크는 통째로 삭제. hot_window 보다 커야 함 | |
consistency | LOCAL_QUORUM | 재인코더가 쓰는 CL. 쿼럼 계열만 허용 | |
interval | 5m | 이 테이블의 재인코딩 주기 |
기간 문법은 <양의 정수><m|h|d> 입니다. 알 수 없는 키나 규칙 위반
(hot_window < chunk_window, cold_window <= hot_window, 쿼럼 미만 CL 등)은
ALTER TABLE 시점에 거부됩니다 — 조용히 무시되지 않습니다.
컬럼 타입이 인코딩을 결정합니다. double 은 ALP/ALP-RD 하나뿐이고, 값이 전혀 변하지 않는
컬럼은 CONSTANT 로, 전부 null 인 컬럼은 ALL_NULL 로 행 수와 무관하게 O(1) 처리됩니다.
정책 JSON 에 codec 키를 넣으면 그 키를 지목해 거부합니다.
해제
ALTER TABLE pp.tm_tag_point WITH extensions = {};
새 인코딩이 멈출 뿐, 이미 청크에 들어간 데이터는 계속 병합되어 보입니다.
운영
# 지금 즉시 한 사이클 (interval 무시)
nodetool retier <keyspace> <table>
# 정책이 걸린 모든 테이블의 상태
nodetool tieringstatus
같은 내용을 CQL 로도 봅니다.
SELECT * FROM system_views.timeseries_tiering;
tags_skipped 가 0 이 아니면 덜 계층화된 것입니다마지막 완료 사이클이 cutoff 까지 다 인코딩하지 못했다는 뜻입니다 — 다른 카운터가 시사하는
만큼 압축되어 있지 않습니다. retier 는 건너뛴 태그가 하나라도 있으면 0 이 아닌 종료 코드로
실패합니다. 원본 행은 손대지 않았으므로 유실은 없습니다. 로그에서 원인을 보고 다시 실행하십시오.
통계는 노드 로컬 · 인메모리이고 마지막 완료 실행 기준입니다 — 재시작하면 초기화됩니다. 여러 노드에서는 각 노드가 자기 primary 토큰 레인지의 태그만 재인코딩해 일을 나눕니다.
알아둘 것
- 콜드 데이터는 불변입니다. 청크에 들어간 구간에 대한 삭제는 거부됩니다.
- 지각 행은 컬럼 단위로 병합됩니다.
- 🔴 파티션 키 없는 전체 스캔 집계는 계층화된 테이블에서 틀린 값을 돌려줍니다. 그 경로는 청크를 병합하지 않습니다. 그런 질의는 Spark SQL 로 보내십시오.
- 페이로드 포맷은 v4 하나입니다. 제거된 옛 포맷을 만나면
SELECT가 조용히 건너뛰지 않고 실패합니다 — 과거 데이터만 빠진 결과를 계속 돌려주는 것보다 낫기 때문입니다.
함께 보기
- 시계열 컴팩션 (TSCS)
- 시계열 함수 — 압축된 구간에서도 그대로 동작합니다