Skip to content

Commit

Permalink
planner: notify skyline pruning of index statistics availability (pin…
Browse files Browse the repository at this point in the history
  • Loading branch information
terry1purcell authored Jan 26, 2025
1 parent 2412351 commit 5ba9e6f
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 12 deletions.
7 changes: 6 additions & 1 deletion pkg/planner/cardinality/selectivity_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ func TestNewIndexWithoutStats(t *testing.T) {
testKit := testkit.NewTestKit(t, store)
testKit.MustExec("use test")
testKit.MustExec("drop table if exists t")
testKit.MustExec("create table t(a int, b int, c int, index idxa(a))")
testKit.MustExec("create table t(a int, b int, c int, index idxa(a), index idxca(c,a))")
testKit.MustExec("set @@tidb_analyze_version=2")
testKit.MustExec("set @@global.tidb_enable_auto_analyze='OFF'")
testKit.MustExec("insert into t values (1, 1, 1)")
Expand All @@ -364,6 +364,11 @@ func TestNewIndexWithoutStats(t *testing.T) {
testKit.MustExec("create index idxab on t(a, b)")
// New index idxab should win due to having the most matching equal predicates - regardless of no statistics
testKit.MustQuery("explain format='brief' select * from t where a = 5 and b = 5").CheckContain("idxab(a, b)")
// New index idxab should win due to having the most predicates - regardless of no statistics
testKit.MustQuery("explain format='brief' select * from t where a > 5 and b > 5").CheckContain("idxab(a, b)")
testKit.MustQuery("explain format='brief' select * from t where a = 5 and b > 5 and c > 5").CheckContain("idxab(a, b)")
// New index idxab should NOT win because idxca has the same number of equals and has statistics
testKit.MustQuery("explain format='brief' select * from t where a = 5 and b > 5 and c = 5").CheckContain("idxca(c, a)")
}

func TestIssue57948(t *testing.T) {
Expand Down
22 changes: 11 additions & 11 deletions pkg/planner/core/find_best_task.go
Original file line number Diff line number Diff line change
Expand Up @@ -760,23 +760,23 @@ func compareCandidates(sctx base.PlanContext, statsTbl *statistics.Table, tableI
// has the same or higher number of equal/IN predicates.
if !lhsPseudo && globalResult >= 0 && sum >= 0 &&
lhs.path.EqOrInCondCount > 0 && lhs.path.EqOrInCondCount >= rhs.path.EqOrInCondCount {
return 1, false // left wins and has statistics
return 1, lhsPseudo // left wins and has statistics (lhsPseudo==false)
}
if !rhsPseudo && globalResult <= 0 && sum <= 0 &&
rhs.path.EqOrInCondCount > 0 && rhs.path.EqOrInCondCount >= lhs.path.EqOrInCondCount {
return -1, false // right wins and has statistics
return -1, rhsPseudo // right wins and has statistics (rhsPseudo==false)
}
if preferRange {
// keep an index without statistics if that index has more equal/IN predicates, AND:
// 1) there are at least 2 equal/INs
// 2) OR - it's a full index match for all index predicates
if lhsPseudo && lhs.path.EqOrInCondCount > rhs.path.EqOrInCondCount && globalResult >= 0 && sum >= 0 &&
(lhs.path.EqOrInCondCount > 1 || (lhs.path.EqOrInCondCount > 0 && len(lhs.indexCondsColMap) >= len(lhs.path.Index.Columns))) {
return 1, true // left wins and does NOT have statistics
return 1, lhsPseudo // left wins and does NOT have statistics (lhsPseudo==true)
}
if rhsPseudo && rhs.path.EqOrInCondCount > lhs.path.EqOrInCondCount && globalResult <= 0 && sum <= 0 &&
(rhs.path.EqOrInCondCount > 1 || (rhs.path.EqOrInCondCount > 0 && len(rhs.indexCondsColMap) >= len(rhs.path.Index.Columns))) {
return -1, true // right wins and does NOT have statistics
return -1, rhsPseudo // right wins and does NOT have statistics (rhsPseudo==true)
}
}
}
Expand All @@ -789,10 +789,10 @@ func compareCandidates(sctx base.PlanContext, statsTbl *statistics.Table, tableI
threshold := float64(fixcontrol.GetIntWithDefault(sctx.GetSessionVars().OptimizerFixControl, fixcontrol.Fix45132, 1000))
if threshold > 0 { // set it to 0 to disable this rule
if lhs.path.CountAfterAccess/rhs.path.CountAfterAccess > threshold {
return -1, false
return -1, rhsPseudo // right wins - also return whether it has statistics (pseudo) or not
}
if rhs.path.CountAfterAccess/lhs.path.CountAfterAccess > threshold {
return 1, false
return 1, lhsPseudo // left wins - also return whether it has statistics (pseudo) or not
}
}
}
Expand All @@ -805,18 +805,18 @@ func compareCandidates(sctx base.PlanContext, statsTbl *statistics.Table, tableI
// If `x` is not worse than `y` at all factors,
// and there exists one factor that `x` is better than `y`, then `x` is better than `y`.
if !comparable1 {
return 0, false
return 0, false // No winner (0). Do not return the pseudo result
}
if !comparable2 {
return 0, false
return 0, false // No winner (0). Do not return the pseudo result
}
if accessResult >= 0 && scanResult >= 0 && matchResult >= 0 && globalResult >= 0 && sum > 0 {
return 1, false
return 1, lhsPseudo // left wins - also return whether it has statistics (pseudo) or not
}
if accessResult <= 0 && scanResult <= 0 && matchResult <= 0 && globalResult <= 0 && sum < 0 {
return -1, false
return -1, rhsPseudo // right wins - also return whether it has statistics (pseudo) or not
}
return 0, false
return 0, false // No winner (0). Do not return the pseudo result
}

func isMatchProp(ds *logicalop.DataSource, path *util.AccessPath, prop *property.PhysicalProperty) bool {
Expand Down

0 comments on commit 5ba9e6f

Please sign in to comment.