Skip to content

Commit be81b25

Browse files
committed
adjust for 7.5 codebase
1 parent 4916d15 commit be81b25

File tree

2 files changed

+47
-2
lines changed

2 files changed

+47
-2
lines changed

pkg/planner/cardinality/selectivity_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,28 @@ func TestEstimationForUnknownValues(t *testing.T) {
284284
require.Equal(t, 0.0, count)
285285
}
286286

287+
func TestNewIndexWithoutStats(t *testing.T) {
288+
store, _ := testkit.CreateMockStoreAndDomain(t)
289+
testKit := testkit.NewTestKit(t, store)
290+
testKit.MustExec("use test")
291+
testKit.MustExec("drop table if exists t")
292+
testKit.MustExec("create table t(a int, b int, c int, index idxa(a))")
293+
testKit.MustExec("set @@tidb_analyze_version=2")
294+
testKit.MustExec("set @@global.tidb_enable_auto_analyze='OFF'")
295+
testKit.MustExec("insert into t values (1, 1, 1)")
296+
testKit.MustExec("insert into t select mod(a,250), mod(a,10), mod(a,100) from (with recursive x as (select 1 as a union all select a + 1 AS a from x where a < 500) select a from x) as subquery")
297+
testKit.MustExec("analyze table t")
298+
testKit.MustExec("create index idxb on t(b)")
299+
// Create index after ANALYZE. SkyLine pruning should ensure that idxa is chosen because it has statistics
300+
testKit.MustQuery("explain format='brief' select * from t where a = 5 and b = 5").CheckContain("idxa(a)")
301+
testKit.MustExec("analyze table t")
302+
// idxa should still win after statistics
303+
testKit.MustQuery("explain format='brief' select * from t where a = 5 and b = 5").CheckContain("idxa(a)")
304+
testKit.MustExec("create index idxab on t(a, b)")
305+
// New index idxab should win due to having the most matching equal predicates - regardless of no statistics
306+
testKit.MustQuery("explain format='brief' select * from t where a = 5 and b = 5").CheckContain("idxab(a, b)")
307+
}
308+
287309
func TestEstimationUniqueKeyEqualConds(t *testing.T) {
288310
store, dom := testkit.CreateMockStoreAndDomain(t)
289311
testKit := testkit.NewTestKit(t, store)

pkg/planner/core/find_best_task.go

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -741,13 +741,36 @@ func compareIndexBack(lhs, rhs *candidatePath) (int, bool) {
741741

742742
// compareCandidates is the core of skyline pruning, which is used to decide which candidate path is better.
743743
// The return value is 1 if lhs is better, -1 if rhs is better, 0 if they are equivalent or not comparable.
744-
func compareCandidates(sctx sessionctx.Context, prop *property.PhysicalProperty, lhs, rhs *candidatePath) int {
744+
func compareCandidates(sctx sessionctx.Context, statisticTable *statistics.Table, prop *property.PhysicalProperty, lhs, rhs *candidatePath) int {
745745
// Due to #50125, full scan on MVIndex has been disabled, so MVIndex path might lead to 'can't find a proper plan' error at the end.
746746
// Avoid MVIndex path to exclude all other paths and leading to 'can't find a proper plan' error, see #49438 for an example.
747747
if isMVIndexPath(lhs.path) || isMVIndexPath(rhs.path) {
748748
return 0
749749
}
750750

751+
lhsHasStatistics := false
752+
if lhs.path.Index != nil {
753+
lhsHasStatistics = statisticTable != nil && statisticTable.Indices[lhs.path.Index.ID] != nil
754+
}
755+
rhsHasStatistics := false
756+
if rhs.path.Index != nil {
757+
rhsHasStatistics = statisticTable != nil && statisticTable.Indices[rhs.path.Index.ID] != nil
758+
}
759+
760+
if !lhs.path.IsTablePath() && !rhs.path.IsTablePath() && // Not a table scan
761+
(lhsHasStatistics || rhsHasStatistics) && // At least one index has statistics
762+
(!lhsHasStatistics || !rhsHasStatistics) && // At least one index doesn't have statistics
763+
len(lhs.path.PartialIndexPaths) == 0 && len(rhs.path.PartialIndexPaths) == 0 { // not IndexMerge due to unreliability
764+
lhsTotalEqual := lhs.path.EqCondCount + lhs.path.EqOrInCondCount
765+
rhsTotalEqual := rhs.path.EqCondCount + rhs.path.EqOrInCondCount
766+
if lhsHasStatistics && lhsTotalEqual > 0 && lhsTotalEqual >= rhsTotalEqual {
767+
return 1
768+
}
769+
if rhsHasStatistics && rhsTotalEqual > 0 && rhsTotalEqual >= lhsTotalEqual {
770+
return -1
771+
}
772+
}
773+
751774
// This rule is empirical but not always correct.
752775
// If x's range row count is significantly lower than y's, for example, 1000 times, we think x is better.
753776
if lhs.path.CountAfterAccess > 100 && rhs.path.CountAfterAccess > 100 && // to prevent some extreme cases, e.g. 0.01 : 10
@@ -918,7 +941,7 @@ func (ds *DataSource) skylinePruning(prop *property.PhysicalProperty) []*candida
918941
if candidates[i].path.StoreType == kv.TiFlash {
919942
continue
920943
}
921-
result := compareCandidates(ds.SCtx(), prop, candidates[i], currentCandidate)
944+
result := compareCandidates(ds.SCtx(), ds.statisticTable, prop, candidates[i], currentCandidate)
922945
if result == 1 {
923946
pruned = true
924947
// We can break here because the current candidate cannot prune others anymore.

0 commit comments

Comments
 (0)