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>
109 lines
5.3 KiB
SQL
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
|