Files
HC900-Crawler/docs/작업지시-history-디지털잔재정리.md
windpacer d88784635e docs: 작업지시·진단·아키텍처 설계 문서 추가
온도프로파일/PV일관성/PointBuilder/history 작업지시, 신호태그·스팀유량 진단, 베이직아키텍처 재설계, MSDS, LLM채팅 구조 등.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 08:12:01 +09:00

4.5 KiB

작업지시: hc900.history_table 디지털 상태점 잔재 정리

다른 LLM/작업자가 이 문서만으로 실행할 수 있도록 작성. 2026-06-09 기준.

목적

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로 설정됨.
  • 실행 중 SnapshotToHistoryAsyncarchive_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, DB iiot_platform, 스키마 hc900.
  • history_table은 일반 테이블(하이퍼테이블 아님). 대량 삭제 후 디스크 회수는 autovacuum이 점진 처리(즉시 필요 시 VACUUM — 라이브 테이블이라 VACUUM FULL 락 주의).
  • 관련: 디지털 검출 기준은 tag_metadata의 state 라벨 보유(과거 i=7594 폐기). 값 N → state{N} 라벨, realtime는 {N | label | } 포맷(Hc900RealtimeService.FormatValue).