Skip to main content

oxirs_arq/optimizer/
execution_tracking.rs

1//! Execution Tracking and Learning
2//!
3//! Records and analyzes query execution for adaptive optimization.
4
5use crate::algebra::Algebra;
6use std::time::Duration;
7
8/// Execution record for learning-based optimization
9#[derive(Debug, Clone)]
10pub struct ExecutionRecord {
11    pub query_hash: u64,
12    pub algebra: Algebra,
13    pub execution_time: Duration,
14    pub cardinality: usize,
15    pub memory_usage: usize,
16    pub optimization_decisions: Vec<OptimizationDecision>,
17}
18
19/// Optimization decision record
20#[derive(Debug, Clone)]
21pub struct OptimizationDecision {
22    pub optimization_type: OptimizationType,
23    pub before_cost: f64,
24    pub after_cost: f64,
25    pub success: bool,
26}
27
28/// Types of optimizations
29#[derive(Debug, Clone)]
30pub enum OptimizationType {
31    JoinReordering,
32    FilterPushdown,
33    ProjectionPushdown,
34    ConstantFolding,
35    IndexSelection,
36    MaterializationPoint,
37    ParallelizationStrategy,
38}
39
40/// Query characteristics for adaptive optimization
41#[derive(Debug, Clone)]
42pub struct QueryCharacteristics {
43    pub variable_count: usize,
44    pub has_object_variables: bool,
45    pub has_literal_constraints: bool,
46    pub join_complexity: JoinComplexity,
47    pub pattern_count: usize,
48}
49
50/// Join complexity classification
51#[derive(Debug, Clone)]
52pub enum JoinComplexity {
53    Simple,   // 1-2 patterns, simple joins
54    Moderate, // 3-5 patterns, some complexity
55    Complex,  // 6+ patterns or complex join patterns
56}
57
58impl ExecutionRecord {
59    /// Create a new execution record
60    pub fn new(query_hash: u64, algebra: Algebra) -> Self {
61        Self {
62            query_hash,
63            algebra,
64            execution_time: Duration::default(),
65            cardinality: 0,
66            memory_usage: 0,
67            optimization_decisions: Vec::new(),
68        }
69    }
70
71    /// Add an optimization decision
72    pub fn add_decision(&mut self, decision: OptimizationDecision) {
73        self.optimization_decisions.push(decision);
74    }
75
76    /// Calculate total optimization benefit
77    pub fn total_benefit(&self) -> f64 {
78        self.optimization_decisions
79            .iter()
80            .map(|d| d.before_cost - d.after_cost)
81            .sum()
82    }
83}
84
85impl OptimizationDecision {
86    /// Create a new optimization decision
87    pub fn new(optimization_type: OptimizationType, before_cost: f64, after_cost: f64) -> Self {
88        Self {
89            optimization_type,
90            before_cost,
91            after_cost,
92            success: after_cost < before_cost,
93        }
94    }
95
96    /// Get the benefit of this optimization
97    pub fn benefit(&self) -> f64 {
98        if self.success {
99            self.before_cost - self.after_cost
100        } else {
101            0.0
102        }
103    }
104}