trading-platform-database-v2/migrations/2026-02-03_add_ml_composite_indexes.sql
Adrian Flores Cortes 6da2786590 [TASK-2026-02-03-ANALISIS-DDL-MODELADO] feat(ddl): FASE-3 Moderate P1 gaps
ST-3.1: Course tags system
- education.course_tags with slug, color, featured flag
- education.course_tag_assignments (M:N) with auto usage_count
- Seeds: 10 initial tags (forex, crypto, ICT, etc.)

ST-3.2: Drawing tools for charts
- Enum: trading.drawing_tool_type (18 types including ICT)
- trading.drawing_tools with JSONB points and styles
- trading.drawing_templates for reusable presets

ST-3.3: Complete agent_executions
- Added 10 columns: execution_time_ms, slippage, risk_score, etc.
- 5 new performance indexes
- Trigger for updated_at

ST-3.4: ML composite indexes
- 8 new composite/partial indexes for predictions
- Optimized for symbol+timeframe+date queries
- Partial indexes for high confidence and overlay display

New files: 7 DDL, 2 migrations, 1 seed
Modified: 3 existing DDL files

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 23:55:24 -06:00

109 lines
5.3 KiB
SQL

-- =====================================================
-- MIGRATION: Add composite indexes to ml.predictions for performance
-- =====================================================
-- Date: 2026-02-03
-- Task: ST-3.4, GAP-008
-- Description: Optimize query performance with composite indexes
-- =====================================================
-- ===========================================
-- COMPOSITE INDEX 1: Symbol + Timeframe + Created
-- ===========================================
-- Query pattern: SELECT * FROM ml.predictions
-- WHERE symbol = ? AND timeframe = ?
-- ORDER BY created_at DESC LIMIT ?
-- Use case: Most common query for fetching latest predictions for a symbol/timeframe
CREATE INDEX IF NOT EXISTS idx_predictions_symbol_timeframe_created
ON ml.predictions(symbol, timeframe, created_at DESC);
-- ===========================================
-- COMPOSITE INDEX 2: Symbol + Prediction Type + Created
-- ===========================================
-- Query pattern: SELECT * FROM ml.predictions
-- WHERE symbol = ? AND prediction_type = ?
-- ORDER BY created_at DESC
-- Use case: Filtered queries by prediction type (e.g., only DIRECTION predictions)
CREATE INDEX IF NOT EXISTS idx_predictions_symbol_type_created
ON ml.predictions(symbol, prediction_type, created_at DESC);
-- ===========================================
-- COMPOSITE INDEX 3: Model + Symbol + Timeframe + Created
-- ===========================================
-- Query pattern: SELECT * FROM ml.predictions
-- WHERE model_id = ? AND symbol = ? AND timeframe = ?
-- ORDER BY created_at DESC
-- Use case: Model-specific prediction queries for analysis and comparison
CREATE INDEX IF NOT EXISTS idx_predictions_model_symbol_timeframe
ON ml.predictions(model_id, symbol, timeframe, created_at DESC);
-- ===========================================
-- COMPOSITE INDEX 4: High Confidence Predictions (Partial)
-- ===========================================
-- Query pattern: SELECT * FROM ml.predictions
-- WHERE symbol = ? AND timeframe = ? AND confidence_score >= 0.7
-- ORDER BY created_at DESC
-- Use case: Fetch only high-confidence predictions for display/alerts
CREATE INDEX IF NOT EXISTS idx_predictions_high_confidence
ON ml.predictions(symbol, timeframe, created_at DESC)
WHERE confidence_score >= 0.7;
-- ===========================================
-- COMPOSITE INDEX 5: Recent Valid Predictions (Partial)
-- ===========================================
-- Query pattern: SELECT * FROM ml.predictions
-- WHERE symbol = ? AND timeframe = ? AND valid_until > NOW()
-- ORDER BY prediction_type, created_at DESC
-- Use case: Active predictions that haven't expired yet
-- Note: Uses immutable predicate-safe pattern (valid_until compared at query time)
CREATE INDEX IF NOT EXISTS idx_predictions_recent_valid
ON ml.predictions(symbol, timeframe, prediction_type, created_at DESC)
WHERE valid_until IS NOT NULL;
-- ===========================================
-- COMPOSITE INDEX 6: Overlay Display for Charts
-- ===========================================
-- Query pattern: SELECT * FROM ml.predictions
-- WHERE symbol = ? AND timeframe = ?
-- AND (chart_config->>'show_on_chart')::boolean = true
-- ORDER BY display_priority DESC, created_at DESC
-- Use case: Chart rendering - fetch predictions configured for display
CREATE INDEX IF NOT EXISTS idx_predictions_overlay_display
ON ml.predictions(symbol, timeframe, display_priority DESC, created_at DESC)
WHERE (chart_config->>'show_on_chart')::boolean = true;
-- ===========================================
-- COMPOSITE INDEX 7: Symbol + Confidence Score (Descending)
-- ===========================================
-- Query pattern: SELECT * FROM ml.predictions
-- WHERE symbol = ?
-- ORDER BY confidence_score DESC
-- Use case: Ranking predictions by confidence for a symbol
CREATE INDEX IF NOT EXISTS idx_predictions_symbol_confidence
ON ml.predictions(symbol, confidence_score DESC, created_at DESC);
-- ===========================================
-- COMPOSITE INDEX 8: Timeframe + Prediction Result + Created
-- ===========================================
-- Query pattern: SELECT * FROM ml.predictions
-- WHERE timeframe = ? AND prediction_result = ?
-- ORDER BY created_at DESC
-- Use case: Cross-symbol analysis of specific prediction results (e.g., all BUY signals on 1H)
CREATE INDEX IF NOT EXISTS idx_predictions_timeframe_result_created
ON ml.predictions(timeframe, prediction_result, created_at DESC)
WHERE prediction_result IS NOT NULL;
-- ===========================================
-- DOCUMENTATION NOTES
-- ===========================================
-- Performance considerations:
-- 1. These indexes are designed for read-heavy workloads
-- 2. Partial indexes reduce storage and improve write performance
-- 3. DESC ordering on timestamps optimizes LIMIT queries for recent data
-- 4. Run ANALYZE after creation in production:
-- ANALYZE ml.predictions;
--
-- Index maintenance:
-- - Monitor pg_stat_user_indexes for usage statistics
-- - Consider REINDEX CONCURRENTLY if fragmentation occurs
-- - Review query plans with EXPLAIN ANALYZE periodically