diff --git a/planner/core/find_best_task.go b/planner/core/find_best_task.go index 6a3918ce479fb..95904ac5a3918 100644 --- a/planner/core/find_best_task.go +++ b/planner/core/find_best_task.go @@ -321,7 +321,38 @@ func getTaskPlanCost(t task, op *physicalOptimizeOp) (float64, bool, error) { case *rootTask: taskType = property.RootTaskType case *copTask: // no need to know whether the task is single-read or double-read, so both CopSingleReadTaskType and CopDoubleReadTaskType are OK + cop := t.(*copTask) + if cop.indexPlan != nil && cop.tablePlan != nil { // handle IndexLookup specially + taskType = property.CopMultiReadTaskType + // keep compatible with the old cost interface, for CopMultiReadTask, the cost is idxCost + tblCost. + if !cop.indexPlanFinished { // only consider index cost in this case + idxCost, err := getPlanCost(cop.indexPlan, taskType, NewDefaultPlanCostOption().WithOptimizeTracer(op)) + return idxCost, false, err + } + // consider both sides + idxCost, err := getPlanCost(cop.indexPlan, taskType, NewDefaultPlanCostOption().WithOptimizeTracer(op)) + if err != nil { + return 0, false, err + } + tblCost, err := getPlanCost(cop.tablePlan, taskType, NewDefaultPlanCostOption().WithOptimizeTracer(op)) + if err != nil { + return 0, false, err + } + return idxCost + tblCost, false, nil + } + taskType = property.CopSingleReadTaskType + + // TiFlash can run cop task as well, check whether this cop task will run on TiKV or TiFlash. + if cop.tablePlan != nil { + leafNode := cop.tablePlan + for len(leafNode.Children()) > 0 { + leafNode = leafNode.Children()[0] + } + if tblScan, isScan := leafNode.(*PhysicalTableScan); isScan && tblScan.StoreType == kv.TiFlash { + taskType = property.MppTaskType + } + } case *mppTask: taskType = property.MppTaskType default: diff --git a/planner/core/plan_cost_ver2_test.go b/planner/core/plan_cost_ver2_test.go index f09897e54be39..37be1316901ef 100644 --- a/planner/core/plan_cost_ver2_test.go +++ b/planner/core/plan_cost_ver2_test.go @@ -280,6 +280,15 @@ func TestIndexJoinPenaltyCost(t *testing.T) { require.Greater(t, cost3, cost2) } +func TestIssue44025(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec(`create table t(a int, b int, c int, d int, index ia(a), index ibc(b,c))`) + tk.MustExec(`set @@tidb_cost_model_version=1`) + tk.MustUseIndex(`select * from t where a between 1 and 5 and b != 200 and c = 20 limit 100000`, `ia(a)`) +} + func BenchmarkGetPlanCost(b *testing.B) { store := testkit.CreateMockStore(b) tk := testkit.NewTestKit(b, store) diff --git a/planner/core/testdata/enforce_mpp_suite_out.json b/planner/core/testdata/enforce_mpp_suite_out.json index 91de0d5bd1348..e62c28ac59cb5 100644 --- a/planner/core/testdata/enforce_mpp_suite_out.json +++ b/planner/core/testdata/enforce_mpp_suite_out.json @@ -51,10 +51,11 @@ { "SQL": "explain format='verbose' select /*+ read_from_storage(tiflash[t]) */ count(*) from t where a=1", "Plan": [ - "StreamAgg_10 1.00 64007.91 root funcs:count(1)->Column#4", - "└─TableReader_24 10.00 63508.91 root data:Selection_23", - " └─Selection_23 10.00 952000.00 cop[tiflash] eq(test.t.a, 1)", - " └─TableFullScan_22 10000.00 928000.00 cop[tiflash] table:t keep order:false, stats:pseudo" + "StreamAgg_20 1.00 63520.28 root funcs:count(Column#6)->Column#4", + "└─TableReader_21 1.00 63470.38 root data:StreamAgg_9", + " └─StreamAgg_9 1.00 952024.00 batchCop[tiflash] funcs:count(1)->Column#6", + " └─Selection_19 10.00 952000.00 batchCop[tiflash] eq(test.t.a, 1)", + " └─TableFullScan_18 10000.00 928000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" ], "Warn": null }, @@ -91,10 +92,11 @@ { "SQL": "explain format='verbose' select /*+ read_from_storage(tiflash[t]) */ count(*) from t where a=1", "Plan": [ - "StreamAgg_12 1.00 64007.91 root funcs:count(1)->Column#4", - "└─TableReader_31 10.00 63508.91 root data:Selection_30", - " └─Selection_30 10.00 952000.00 cop[tiflash] eq(test.t.a, 1)", - " └─TableFullScan_29 10000.00 928000.00 cop[tiflash] table:t keep order:false, stats:pseudo" + "StreamAgg_27 1.00 63520.28 root funcs:count(Column#7)->Column#4", + "└─TableReader_28 1.00 63470.38 root data:StreamAgg_11", + " └─StreamAgg_11 1.00 952024.00 batchCop[tiflash] funcs:count(1)->Column#7", + " └─Selection_26 10.00 952000.00 batchCop[tiflash] eq(test.t.a, 1)", + " └─TableFullScan_25 10000.00 928000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" ], "Warn": null }, @@ -126,10 +128,11 @@ { "SQL": "explain format='verbose' select /*+ read_from_storage(tiflash[t]) */ count(*) from t where a=1", "Plan": [ - "StreamAgg_12 1.00 64007.91 root funcs:count(1)->Column#4", - "└─TableReader_31 10.00 63508.91 root data:Selection_30", - " └─Selection_30 10.00 952000.00 cop[tiflash] eq(test.t.a, 1)", - " └─TableFullScan_29 10000.00 928000.00 cop[tiflash] table:t keep order:false, stats:pseudo" + "StreamAgg_27 1.00 63520.28 root funcs:count(Column#7)->Column#4", + "└─TableReader_28 1.00 63470.38 root data:StreamAgg_11", + " └─StreamAgg_11 1.00 952024.00 batchCop[tiflash] funcs:count(1)->Column#7", + " └─Selection_26 10.00 952000.00 batchCop[tiflash] eq(test.t.a, 1)", + " └─TableFullScan_25 10000.00 928000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" ], "Warn": null }, @@ -165,8 +168,8 @@ "Plan": [ "StreamAgg_27 1.00 49.90 root funcs:count(Column#7)->Column#4", "└─TableReader_28 1.00 0.00 root data:StreamAgg_11", - " └─StreamAgg_11 1.00 1427024.00 batchCop[tiflash] funcs:count(1)->Column#7", - " └─Selection_26 10.00 1427000.00 batchCop[tiflash] eq(test.t.a, 1)", + " └─StreamAgg_11 1.00 952024.00 batchCop[tiflash] funcs:count(1)->Column#7", + " └─Selection_26 10.00 952000.00 batchCop[tiflash] eq(test.t.a, 1)", " └─TableFullScan_25 10000.00 928000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" ], "Warn": null