Use HashJoin in BGP if no shared variables

Allows avoiding reading multiple times the same table
pull/171/head
Tpt 3 years ago
parent 19c862228a
commit 32660ecfba
  1. 60
      lib/src/sparql/plan_builder.rs

@ -52,10 +52,7 @@ impl<'a> PlanBuilder<'a> {
object: self.pattern_value_from_term_or_variable(&triple.object, variables),
graph_name: graph_name.clone(),
})
.reduce(|left, right| PlanNode::ForLoopJoin {
left: Box::new(left),
right: Box::new(right),
})
.reduce(Self::new_join)
.unwrap_or_else(|| PlanNode::StaticBindings {
tuples: vec![EncodedTuple::with_capacity(variables.len())],
}),
@ -69,28 +66,10 @@ impl<'a> PlanBuilder<'a> {
object: self.pattern_value_from_term_or_variable(object, variables),
graph_name: graph_name.clone(),
},
GraphPattern::Join { left, right } => {
let left = self.build_for_graph_pattern(left, variables, graph_name)?;
let right = self.build_for_graph_pattern(right, variables, graph_name)?;
if self.is_fit_for_for_loop_join(&left)
&& self.is_fit_for_for_loop_join(&right)
&& left
.always_bound_variables()
.intersection(&right.always_bound_variables())
.next()
.is_some()
{
PlanNode::ForLoopJoin {
left: Box::new(left),
right: Box::new(right),
}
} else {
PlanNode::HashJoin {
left: Box::new(left),
right: Box::new(right),
}
}
}
GraphPattern::Join { left, right } => Self::new_join(
self.build_for_graph_pattern(left, variables, graph_name)?,
self.build_for_graph_pattern(right, variables, graph_name)?,
),
GraphPattern::LeftJoin {
left,
right,
@ -1152,7 +1131,28 @@ impl<'a> PlanBuilder<'a> {
}
}
fn is_fit_for_for_loop_join(&self, node: &PlanNode) -> bool {
fn new_join(left: PlanNode, right: PlanNode) -> PlanNode {
if Self::is_fit_for_for_loop_join(&left)
&& Self::is_fit_for_for_loop_join(&right)
&& left
.always_bound_variables()
.intersection(&right.always_bound_variables())
.next()
.is_some()
{
PlanNode::ForLoopJoin {
left: Box::new(left),
right: Box::new(right),
}
} else {
PlanNode::HashJoin {
left: Box::new(left),
right: Box::new(right),
}
}
}
fn is_fit_for_for_loop_join(node: &PlanNode) -> bool {
//TODO: think more about it
match node {
PlanNode::StaticBindings { .. }
@ -1160,13 +1160,13 @@ impl<'a> PlanBuilder<'a> {
| PlanNode::PathPattern { .. }
| PlanNode::ForLoopJoin { .. } => true,
PlanNode::HashJoin { left, right } => {
self.is_fit_for_for_loop_join(left) && self.is_fit_for_for_loop_join(right)
Self::is_fit_for_for_loop_join(left) && Self::is_fit_for_for_loop_join(right)
}
PlanNode::Filter { child, .. } | PlanNode::Extend { child, .. } => {
self.is_fit_for_for_loop_join(child)
Self::is_fit_for_for_loop_join(child)
}
PlanNode::Union { children } => {
children.iter().all(|c| self.is_fit_for_for_loop_join(c))
children.iter().all(|c| Self::is_fit_for_for_loop_join(c))
}
PlanNode::AntiJoin { .. }
| PlanNode::LeftJoin { .. }

Loading…
Cancel
Save