Skip to content

Commit f0fd9fa

Browse files
committed
join-reordering
1 parent 61b4f1c commit f0fd9fa

3 files changed

Lines changed: 678 additions & 0 deletions

File tree

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
use datafusion_common::{Result, plan_err};
19+
use datafusion_expr::{JoinType, LogicalPlan};
20+
21+
use super::query_graph::Edge;
22+
23+
pub trait JoinCostEstimator: std::fmt::Debug {
24+
fn cardinality(&self, plan: &LogicalPlan) -> Option<f64> {
25+
estimate_cardinality(plan).ok()
26+
}
27+
28+
fn selectivity(&self, edge: &Edge) -> f64 {
29+
match edge.join_type {
30+
JoinType::Inner => 0.1,
31+
_ => 1.0,
32+
}
33+
}
34+
35+
fn cost(&self, selectivity: f64, cardinality: f64) -> f64 {
36+
selectivity * cardinality
37+
}
38+
}
39+
40+
/// Default implementation of JoinCostEstimator
41+
#[derive(Debug, Clone, Copy)]
42+
pub struct DefaultCostEstimator;
43+
44+
impl JoinCostEstimator for DefaultCostEstimator {}
45+
46+
fn estimate_cardinality(plan: &LogicalPlan) -> Result<f64> {
47+
match plan {
48+
LogicalPlan::Filter(filter) => {
49+
let input_cardinality = estimate_cardinality(&filter.input)?;
50+
Ok(0.1 * input_cardinality)
51+
}
52+
LogicalPlan::Aggregate(agg) => {
53+
let input_cardinality = estimate_cardinality(&agg.input)?;
54+
Ok(0.1 * input_cardinality)
55+
}
56+
LogicalPlan::TableScan(_) => {
57+
// The logical-plan-level `TableSource` trait doesn't expose row
58+
// statistics. To use cardinalities for base relations, override
59+
// `JoinCostEstimator::cardinality`.
60+
plan_err!(
61+
"Default JoinCostEstimator cannot size TableScan; \
62+
override `cardinality` to provide statistics"
63+
)
64+
}
65+
x => {
66+
let inputs = x.inputs();
67+
if inputs.len() == 1 {
68+
estimate_cardinality(inputs[0])
69+
} else {
70+
plan_err!("Cannot estimate cardinality for plan with multiple inputs")
71+
}
72+
}
73+
}
74+
}

0 commit comments

Comments
 (0)