-- 쿼리 실행 메트릭 테이블 -- WebSocket/REST 쿼리의 성능 지표를 기록하여 ApiMetrics 페이지에서 조회 CREATE TABLE IF NOT EXISTS signal.t_query_metrics ( id BIGSERIAL PRIMARY KEY, query_id VARCHAR(64) NOT NULL, session_id VARCHAR(64), query_type VARCHAR(20) NOT NULL, -- 'WEBSOCKET' | 'REST_V1' | 'REST_V2' created_at TIMESTAMP NOT NULL DEFAULT now(), -- 요청 파라미터 start_time TIMESTAMP, end_time TIMESTAMP, zoom_level INTEGER, viewport_bounds VARCHAR(200), -- "minLon,minLat,maxLon,maxLat" requested_mmsi INTEGER DEFAULT 0, -- 처리 경로 data_path VARCHAR(10), -- 'CACHE' | 'DB' | 'HYBRID' cache_hit_days INTEGER DEFAULT 0, db_query_days INTEGER DEFAULT 0, db_conn_total INTEGER DEFAULT 0, -- 결과 통계 unique_vessels INTEGER DEFAULT 0, total_tracks INTEGER DEFAULT 0, total_points INTEGER DEFAULT 0, points_after_simplify INTEGER DEFAULT 0, total_chunks INTEGER DEFAULT 0, response_bytes BIGINT DEFAULT 0, -- 성능 elapsed_ms BIGINT DEFAULT 0, db_query_ms BIGINT DEFAULT 0, simplify_ms BIGINT DEFAULT 0, backpressure_events INTEGER DEFAULT 0, -- 결과 상태 status VARCHAR(20) DEFAULT 'COMPLETED' -- 'COMPLETED' | 'CANCELLED' | 'ERROR' | 'TIMEOUT' ); -- client_ip 컬럼 추가 (idempotent) DO $$ BEGIN IF NOT EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_schema = 'signal' AND table_name = 't_query_metrics' AND column_name = 'client_ip' ) THEN ALTER TABLE signal.t_query_metrics ADD COLUMN client_ip VARCHAR(45); END IF; END $$; CREATE INDEX IF NOT EXISTS idx_query_metrics_created ON signal.t_query_metrics(created_at); CREATE INDEX IF NOT EXISTS idx_query_metrics_type ON signal.t_query_metrics(query_type, created_at); CREATE INDEX IF NOT EXISTS idx_query_metrics_client_ip ON signal.t_query_metrics(client_ip, created_at);