Skip to content

Commit

Permalink
Fixes an issue in selectivity calculation, which leads to absolute va…
Browse files Browse the repository at this point in the history
…lues instead of relative ones.
  • Loading branch information
ppanopticon committed May 24, 2024
1 parent a899c17 commit e08a061
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ object NaiveSelectivityCalculator {
is BooleanPredicate.IsNull -> this.estimateIsNull(predicate, statistics)
is BooleanPredicate.Comparison -> this.estimateComparison(predicate, statistics)
is BooleanPredicate.Not -> Selectivity(1.0f - this.estimate(predicate.p, statistics).value)
is BooleanPredicate.And -> this.estimate(predicate.p1, statistics) * this.estimate(predicate.p2, statistics)
is BooleanPredicate.And -> {
val pp1 = this.estimate(predicate.p1, statistics)
val pp2 = this.estimate(predicate.p2, statistics)
pp1 * pp2
}
is BooleanPredicate.Or -> {
val pp1 = this.estimate(predicate.p1, statistics)
val pp2 = this.estimate(predicate.p2, statistics)
Expand Down Expand Up @@ -69,8 +73,9 @@ object NaiveSelectivityCalculator {
val right = predicate.operator.right
return when {
left is Binding.Literal && right is Binding.Literal -> if (left.getValue() == right.getValue()) Selectivity.ALL else Selectivity.NOTHING
left is Binding.Literal && right is Binding.Column -> statistics[right.column]?.estimateSelectivity(predicate) ?: Selectivity.DEFAULT
left is Binding.Column && right is Binding.Literal -> statistics[left.column]?.estimateSelectivity(predicate) ?: Selectivity.DEFAULT
left is Binding.Literal && right is Binding.Column -> statistics[right.physical]?.estimateSelectivity(predicate) ?: Selectivity.DEFAULT
left is Binding.Column && right is Binding.Literal -> statistics[left.physical]?.estimateSelectivity(predicate) ?: Selectivity.DEFAULT
left is Binding.Column && right is Binding.LiteralList -> statistics[left.physical]?.estimateSelectivity(predicate) ?: Selectivity.DEFAULT
else -> Selectivity.DEFAULT
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,28 +75,29 @@ sealed class AbstractValueStatistics<T : Value>(override val type: Types<T>) : V
* @return [Selectivity] estimate.
*/
context(BindingContext, Tuple)
override fun estimateSelectivity(predicate: BooleanPredicate.Comparison): Selectivity = when(val operator = predicate.operator){
/* =: Textbook definition using estimate for number if distinct entries. */
is ComparisonOperator.Equal -> Selectivity(this.numberOfEntries.toFloat() / this.numberOfDistinctEntries.toFloat()) // Case Equality =

/* !=: Textbook definition using estimate for number if distinct entries. */
is ComparisonOperator.NotEqual -> Selectivity(this.numberOfEntries.toFloat() * (this.numberOfDistinctEntries.toFloat() - 1f) / this.numberOfDistinctEntries.toFloat()) //Case Not-equals (like A != 10)

/* <, >, <=, >=: Textbook definition. Assumption is, that 1/3 of the collection is selected (see [1]) */
is ComparisonOperator.Greater,
is ComparisonOperator.Less,
is ComparisonOperator.GreaterEqual,
is ComparisonOperator.LessEqual -> Selectivity(this.numberOfEntries.toFloat() / 3f)

/* BETWEEN: Assumption is, that it returns fewer tuples than a less/greater operator (since it's a composition of both using AND). */
is ComparisonOperator.Between -> Selectivity(this.numberOfEntries.toFloat() / 6f) //

/* IN: Assumption is, that all elements in IN are matches (worst-case). */
is ComparisonOperator.In -> Selectivity(operator.right.size() * this.numberOfEntries.toFloat() / this.numberOfDistinctEntries.toFloat())

// Default case:
else -> Selectivity.DEFAULT
override fun estimateSelectivity(predicate: BooleanPredicate.Comparison): Selectivity {
val selected = when(val operator = predicate.operator){
/* =: Textbook definition using estimate for number of distinct entries. */
is ComparisonOperator.Equal -> this.numberOfEntries.toFloat() / this.numberOfDistinctEntries.toFloat()

/* !=: Textbook definition using estimate for number if distinct entries. */
is ComparisonOperator.NotEqual ->this.numberOfEntries.toFloat() * (this.numberOfDistinctEntries.toFloat() - 1f) / this.numberOfDistinctEntries.toFloat() //Case Not-equals (like A != 10)

/* <, >, <=, >=: Textbook definition. Assumption is, that 1/3 of the collection is selected (see [1]) */
is ComparisonOperator.Greater,
is ComparisonOperator.Less,
is ComparisonOperator.GreaterEqual,
is ComparisonOperator.LessEqual -> this.numberOfEntries.toFloat() / 3f

/* BETWEEN: Assumption is, that it returns fewer tuples than a less/greater operator (since it's a composition of both using AND). */
is ComparisonOperator.Between -> this.numberOfEntries.toFloat() / 6f //

/* IN: Assumption is, that all elements IN are matches (worst-case). */
is ComparisonOperator.In -> (operator.right.size() * this.numberOfEntries.toFloat()) / this.numberOfDistinctEntries.toFloat()

// Default case:
else -> this.numberOfEntries / 3f
}
return Selectivity(selected / this.numberOfEntries.toFloat())
}


}

0 comments on commit e08a061

Please sign in to comment.