use std::collections::HashMap;
use std::time::Duration;
use super::execution_tracking::{ExecutionRecord, OptimizationDecision, OptimizationType};
use super::index_types::{IndexStatistics, IndexType};
use crate::algebra::Variable;
#[derive(Debug, Clone, Default)]
pub struct Statistics {
pub index_stats: HashMap<IndexType, IndexStatistics>,
pub join_selectivities: HashMap<String, f64>,
pub filter_selectivities: HashMap<String, f64>,
pub execution_times: HashMap<String, Duration>,
pub cardinalities: HashMap<String, usize>,
pub pattern_cardinality: HashMap<String, usize>,
pub predicate_frequency: HashMap<String, usize>,
pub subject_cardinality: HashMap<String, usize>,
pub object_cardinality: HashMap<String, usize>,
pub variable_selectivity: HashMap<Variable, f64>,
pub optimization_success_rates: HashMap<OptimizationType, f64>,
pub total_queries: usize,
pub total_optimization_time: Duration,
}
impl Statistics {
pub fn new() -> Self {
Self::default()
}
pub fn update_with_execution(&mut self, record: &ExecutionRecord) {
self.total_queries += 1;
for decision in &record.optimization_decisions {
self.update_optimization_success_rate(decision);
}
let query_hash = record.query_hash.to_string();
self.execution_times
.insert(query_hash.clone(), record.execution_time);
self.cardinalities.insert(query_hash, record.cardinality);
}
pub fn update_index_stats(&mut self, index_type: IndexType, stats: IndexStatistics) {
self.index_stats.insert(index_type, stats);
}
pub fn get_join_selectivity(&self, join_pattern: &str) -> Option<f64> {
self.join_selectivities.get(join_pattern).copied()
}
pub fn set_join_selectivity(&mut self, join_pattern: String, selectivity: f64) {
self.join_selectivities.insert(join_pattern, selectivity);
}
pub fn get_filter_selectivity(&self, filter_pattern: &str) -> Option<f64> {
self.filter_selectivities.get(filter_pattern).copied()
}
pub fn set_filter_selectivity(&mut self, filter_pattern: String, selectivity: f64) {
self.filter_selectivities
.insert(filter_pattern, selectivity);
}
pub fn get_estimated_cardinality(&self, pattern: &str) -> Option<usize> {
self.cardinalities.get(pattern).copied()
}
pub fn get_optimization_success_rate(&self, opt_type: &OptimizationType) -> f64 {
self.optimization_success_rates
.get(opt_type)
.copied()
.unwrap_or(0.5) }
pub fn add_optimization_time(&mut self, duration: Duration) {
self.total_optimization_time += duration;
}
pub fn average_optimization_time(&self) -> Duration {
if self.total_queries > 0 {
self.total_optimization_time / self.total_queries as u32
} else {
Duration::default()
}
}
fn update_optimization_success_rate(&mut self, decision: &OptimizationDecision) {
let current_rate = self
.optimization_success_rates
.get(&decision.optimization_type)
.copied()
.unwrap_or(0.5);
let alpha = 0.1;
let success_value = if decision.success { 1.0 } else { 0.0 };
let new_rate = alpha * success_value + (1.0 - alpha) * current_rate;
self.optimization_success_rates
.insert(decision.optimization_type.clone(), new_rate);
}
}
impl PartialEq for OptimizationType {
fn eq(&self, other: &Self) -> bool {
std::mem::discriminant(self) == std::mem::discriminant(other)
}
}
impl Eq for OptimizationType {}
impl std::hash::Hash for OptimizationType {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
std::mem::discriminant(self).hash(state);
}
}