온라인 히스토리안 3계층 — 실시간 KPI를 history_1s에서 산출·캐싱. - 메트릭 소스 일반화: history_table | history_1s | history_1min_src | fast_record. history_1min_src = 연속집계 드롭인 호환뷰(bucket→recorded_at). - Hc900LiveKpiService: 매 15s 오늘(KST) 컬럼별 KPI(production/yield/energy/closure)를 history_1s에서 재계산해 live_kpi upsert. 재계산=러닝상태의 stateless 동등판(causal 동치, 크래시 복구 불필요). 컬럼 state(normal/idle/error) 산출. - live_kpi 테이블 + GET /api/report/live 조회 엔드포인트. - Report:LiveKpi config(Enabled/IntervalSeconds/Source). 검증: 라이브 live_kpi 28행(7컬럼×4KPI) 15s 갱신, /live 정상. 데모 sim은 totalizer가 평평해 값 0/idle(플러밍 정상, 실데이터면 실값). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
46 lines
2.3 KiB
SQL
46 lines
2.3 KiB
SQL
-- P1a: 1초 링버퍼 히스토리안 (hc900.history_1s)
|
|
-- 적용: psql "host=localhost dbname=iiot_platform user=postgres" -f scripts/sql/p1_historian.sql
|
|
-- 서비스(Hc900FastHistoryService)가 기동 시 동일 DDL을 멱등 적용하므로 수동 실행은 선택.
|
|
SET search_path TO hc900;
|
|
|
|
CREATE TABLE IF NOT EXISTS hc900.history_1s (
|
|
tagname text NOT NULL,
|
|
recorded_at timestamptz NOT NULL DEFAULT now(),
|
|
value text,
|
|
controller_id text
|
|
);
|
|
|
|
-- 하이퍼테이블 (1시간 청크 — evict/압축 단위)
|
|
SELECT create_hypertable('hc900.history_1s', 'recorded_at',
|
|
chunk_time_interval => INTERVAL '1 hour', if_not_exists => TRUE);
|
|
|
|
-- 압축 (6시간 지난 청크) + 링버퍼 보존 (14일 — 청크 DROP, 비용≈0)
|
|
ALTER TABLE hc900.history_1s SET (timescaledb.compress, timescaledb.compress_segmentby = 'tagname');
|
|
SELECT add_compression_policy('hc900.history_1s', INTERVAL '6 hours', if_not_exists => TRUE);
|
|
SELECT add_retention_policy('hc900.history_1s', INTERVAL '14 days', if_not_exists => TRUE);
|
|
|
|
CREATE INDEX IF NOT EXISTS ix_h1s_tag ON hc900.history_1s (tagname, recorded_at DESC);
|
|
|
|
-- P1b: 연속집계 history_1min — 1초 버퍼 evict 전 60초 롤업(장기 무손실, 2계층)
|
|
CREATE MATERIALIZED VIEW IF NOT EXISTS hc900.history_1min
|
|
WITH (timescaledb.continuous) AS
|
|
SELECT time_bucket('1 minute', recorded_at) AS bucket, tagname,
|
|
last(value, recorded_at) AS value, last(controller_id, recorded_at) AS controller_id
|
|
FROM hc900.history_1s GROUP BY bucket, tagname
|
|
WITH NO DATA;
|
|
|
|
-- 집계 lag(≤3h) ≪ 보존 윈도(14일) → raw 삭제 전 materialize 보장
|
|
SELECT add_continuous_aggregate_policy('hc900.history_1min',
|
|
start_offset => INTERVAL '3 hours', end_offset => INTERVAL '10 minutes',
|
|
schedule_interval => INTERVAL '5 minutes', if_not_exists => TRUE);
|
|
|
|
-- P1c: 메트릭엔진 드롭인 소스(bucket→recorded_at) + 온라인 KPI 누적 테이블
|
|
CREATE OR REPLACE VIEW hc900.history_1min_src AS
|
|
SELECT tagname, bucket AS recorded_at, value, controller_id FROM hc900.history_1min;
|
|
|
|
CREATE TABLE IF NOT EXISTS hc900.live_kpi (
|
|
column_id text NOT NULL, kpi text NOT NULL, window_start date NOT NULL,
|
|
value double precision, unit text, state text, excluded_min int, status text,
|
|
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
PRIMARY KEY (column_id, kpi, window_start));
|