- docs/작업지시-history-디지털잔재정리.md: SUPERSEDED 배너(실행 금지). 2026-06-18 실측 — 삭제대상(비-archive ~2천만)은 디지털 잔재 0, 전부 아날로그 루프/적산. 특히 .QV는 리포트(history_table)가 의존 → 삭제 시 과거 리포트 파손. - scripts/sql/report_keep_qv_tags.sql: SteamFlow 적산 FIQ-*.QV 7개를 archive_enabled=TRUE로 재분류(register-map 누락 보정). realtime/is_active=FALSE 로 폴링 부작용 0. 멱등(map 재빌드 후 재적용). DB에는 이미 적용. 검증: 리포트 태그 삭제대상 0행, 전체 삭제대상 19.98M→17.62M(2.36M 보호). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
6.0 KiB
작업지시: hc900.history_table 디지털 상태점 잔재 정리
⛔ SUPERSEDED — 실행 금지 (2026-06-18 검증으로 폐기). 이 문서의 삭제 절차(§2·§3)를 실행하지 말 것. 작성 시점(2026-06-09) 이후 P0/P2 셀프서비스 리포트가 추가되면서 전제가 무효가 되었다.
2026-06-18 실측 분석 결과 —
archive_enabled=FALSE삭제대상(약 2천만 행)의 구성:
속성 행수 숫자비율 정체 .QV5.45M 95% 적산 totalizer — 리포트 production_total/mass_balance_closure가 history_table에서 직접 읽음 .HZ/.HZSET8.88M 100% 펌프 주파수 .PV2.62M 100% 공정 측정값 .SP/.OP/.LSET3.03M 100% 설정·출력·리미트
- 삭제대상에 디지털 상태점(state 라벨/비숫자) 행은 0개 — 원래 목표였던 디지털 잔재는 이미 정리 완료 상태다(history_table에 남아있지 않음).
- 남은 비-archive는 잔재가 아니라 루프 내부 파라미터 + 적산값이며, 특히
.QV는 리포트 기본 소스(history_table)에서 메트릭이 의존한다. 삭제 시 과거 일/월/연 리포트가 깨진다.- 후속 조치(완료): 리포트 의존
.QV7개(FIQ-6115/6215/8115/9115/9215/10115/10215.QV)가 register-map 누락으로 keep에서 빠져 있어archive_enabled=TRUE로 재분류 →scripts/sql/report_keep_qv_tags.sql(멱등, map 재빌드 후 재적용). 디지털 잔재 정리 자체는 완료로 종결.아래 원문은 이력 보존용으로만 남긴다.
목적 (원문 — 폐기됨)
hc900.history_table에는 디지털 상태점(예: AG-3202, C3601_RUN, CH-5601 —
{0 | L-STOP | } 형태, state 라벨 보유)의 과거 이력 약 15만 행이 잘못 쌓여 있다.
이들은 상태변경 이벤트라 event_history_table로 가야 하며 history_table(연속
측정값 60초 스냅샷)에는 있으면 안 된다.
이미 처리된 것(배경):
- register-map 재작성으로 디지털 상태점(StatusPoint PV)은 map_master에서
archive_enabled = FALSE로 설정됨. - 실행 중
SnapshotToHistoryAsync는archive_enabled+ 디지털 제외(state 라벨)로 신규 디지털 행을 더는 적재하지 않음(검증됨: 재시작 후 신규 유입 0). - 따라서 남은 과거 잔재만 삭제하면 된다. (비가역 → 반드시 백업 먼저)
판정 기준
history_table에서 archive_enabled가 아닌 (controller_id, tagname) 행을 삭제한다.
이는 디지털 상태점 + 루프 내부 파라미터 등 비-archive 태그를 모두 정리한다.
유지: archive_enabled=TRUE (루프 PV/SP/OP/MD/QV + 아날로그 신호태그).
주의: 행수는 시점에 따라 변하므로 실행 시점에 live로 재계산할 것. 아래는 절차.
실행 절차 (복붙 가능)
1) 규모 확인
docker exec iiot-timescaledb psql -U postgres -d iiot_platform -At -c "
WITH arch AS (SELECT controller_id, tagname FROM hc900.hc900_map_master WHERE archive_enabled)
SELECT 'keep_rows', count(*) FROM hc900.history_table h
WHERE EXISTS (SELECT 1 FROM arch a WHERE a.tagname=h.tagname AND (a.controller_id=h.controller_id OR h.controller_id IS NULL))
UNION ALL
SELECT 'delete_rows', count(*) FROM hc900.history_table h
WHERE NOT EXISTS (SELECT 1 FROM arch a WHERE a.tagname=h.tagname AND (a.controller_id=h.controller_id OR h.controller_id IS NULL));
"
2) 백업 (gzip CSV) — 삭제 대상 행
BK=/home/windpacer/db_backups; mkdir -p "$BK"
TS=$(date +%Y%m%d)
docker exec iiot-timescaledb psql -U postgres -d iiot_platform -c "
COPY (
SELECT h.* FROM hc900.history_table h
WHERE NOT EXISTS (
SELECT 1 FROM hc900.hc900_map_master a
WHERE a.archive_enabled AND a.tagname=h.tagname
AND (a.controller_id=h.controller_id OR h.controller_id IS NULL))
) TO STDOUT WITH CSV HEADER" | gzip > "$BK/history_nonarchive_digital_$TS.csv.gz"
echo "backup rows: $(( $(zcat "$BK/history_nonarchive_digital_$TS.csv.gz" | wc -l) - 1 ))"
ls -lh "$BK/history_nonarchive_digital_$TS.csv.gz"
→ 백업 행수가 1단계 delete_rows와 정확히 일치하는지 확인. 불일치면 중단.
3) 삭제 (트랜잭션)
docker exec iiot-timescaledb psql -U postgres -d iiot_platform -v ON_ERROR_STOP=1 -c "
BEGIN;
DELETE FROM hc900.history_table h
WHERE NOT EXISTS (
SELECT 1 FROM hc900.hc900_map_master a
WHERE a.archive_enabled AND a.tagname=h.tagname
AND (a.controller_id=h.controller_id OR h.controller_id IS NULL));
COMMIT;
"
4) 검증
docker exec iiot-timescaledb psql -U postgres -d iiot_platform -At -c "
WITH dig AS (SELECT DISTINCT base_tag FROM hc900.tag_metadata WHERE attribute LIKE 'state%' AND value<>'')
SELECT 'history_rows', count(*)::text FROM hc900.history_table
UNION ALL SELECT 'history_distinct_tags', count(DISTINCT tagname)::text FROM hc900.history_table
UNION ALL SELECT 'digital_tags_left (0이어야)', count(*)::text FROM (
SELECT DISTINCT tagname FROM hc900.history_table WHERE tagname IN (SELECT base_tag FROM dig)) x;
"
→ digital_tags_left = 0, 남은 태그는 archive_enabled 집합과 일치해야 한다.
복구 (필요 시)
zcat /home/windpacer/db_backups/history_nonarchive_digital_<TS>.csv.gz | \
docker exec -i iiot-timescaledb psql -U postgres -d iiot_platform \
-c "COPY hc900.history_table FROM STDIN WITH CSV HEADER"
참고
- DB: PostgreSQL/TimescaleDB 컨테이너
iiot-timescaledb, DBiiot_platform, 스키마hc900. history_table은 일반 테이블(하이퍼테이블 아님). 대량 삭제 후 디스크 회수는 autovacuum이 점진 처리(즉시 필요 시VACUUM— 라이브 테이블이라VACUUM FULL락 주의).- 관련: 디지털 검출 기준은
tag_metadata의 state 라벨 보유(과거i=7594폐기). 값 N → state{N} 라벨, realtime는{N | label | }포맷(Hc900RealtimeService.FormatValue).