From 75fa714ab410652b20c5a7dbeda962ec02a3dd53 Mon Sep 17 00:00:00 2001 From: Ti Chi Robot Date: Tue, 21 May 2024 13:22:15 +0800 Subject: [PATCH] planner: fix the issue that MVIndex leads to "can't find plan" error (#52067) (#52173) close pingcap/tidb#49438 --- pkg/planner/core/casetest/BUILD.bazel | 2 +- pkg/planner/core/casetest/integration_test.go | 9 +++++++++ pkg/planner/core/find_best_task.go | 6 ++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/pkg/planner/core/casetest/BUILD.bazel b/pkg/planner/core/casetest/BUILD.bazel index 1cc904c9c3d29..2baabf61e3ca3 100644 --- a/pkg/planner/core/casetest/BUILD.bazel +++ b/pkg/planner/core/casetest/BUILD.bazel @@ -12,7 +12,7 @@ go_test( ], data = glob(["testdata/**"]), flaky = True, - shard_count = 22, + shard_count = 23, deps = [ "//pkg/domain", "//pkg/parser", diff --git a/pkg/planner/core/casetest/integration_test.go b/pkg/planner/core/casetest/integration_test.go index e51d599664097..ae8f54f9f8013 100644 --- a/pkg/planner/core/casetest/integration_test.go +++ b/pkg/planner/core/casetest/integration_test.go @@ -442,6 +442,15 @@ func TestFixControl45132(t *testing.T) { tk.MustHavePlan(`select * from t where a=2`, `TableFullScan`) } +func TestIssue49438(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec(`use test`) + tk.MustExec(`drop table if exists tx`) + tk.MustExec(`create table tx (a int, b json, key k(a, (cast(b as date array))))`) + tk.MustExec(`select 1 from tx where a in (1)`) // no error +} + func TestIssue41957(t *testing.T) { store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) diff --git a/pkg/planner/core/find_best_task.go b/pkg/planner/core/find_best_task.go index dd19f6e2d0ed4..c89bd519b90b4 100644 --- a/pkg/planner/core/find_best_task.go +++ b/pkg/planner/core/find_best_task.go @@ -725,6 +725,12 @@ func compareIndexBack(lhs, rhs *candidatePath) (int, bool) { // compareCandidates is the core of skyline pruning, which is used to decide which candidate path is better. // The return value is 1 if lhs is better, -1 if rhs is better, 0 if they are equivalent or not comparable. func compareCandidates(sctx sessionctx.Context, prop *property.PhysicalProperty, lhs, rhs *candidatePath) int { + // 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. + // Avoid MVIndex path to exclude all other paths and leading to 'can't find a proper plan' error, see #49438 for an example. + if isMVIndexPath(lhs.path) || isMVIndexPath(rhs.path) { + return 0 + } + // This rule is empirical but not always correct. // If x's range row count is significantly lower than y's, for example, 1000 times, we think x is better. if lhs.path.CountAfterAccess > 100 && rhs.path.CountAfterAccess > 100 && // to prevent some extreme cases, e.g. 0.01 : 10