From 3068ce14ce51d9abe03045a0742ee7dac13ef1c8 Mon Sep 17 00:00:00 2001 From: Ti Chi Robot Date: Thu, 25 Jan 2024 16:37:51 +0800 Subject: [PATCH] planner: fix leading hint cannot take effect in UNION ALL statements (#50277) (#50722) close pingcap/tidb#50067 --- pkg/planner/core/casetest/hint/BUILD.bazel | 2 +- pkg/planner/core/casetest/hint/hint_test.go | 26 ++++++ .../hint/testdata/integration_suite_in.json | 6 ++ .../hint/testdata/integration_suite_out.json | 43 ++++++++- pkg/planner/core/logical_plan_builder.go | 4 +- pkg/planner/core/planbuilder.go | 2 +- pkg/planner/core/rule_join_reorder_greedy.go | 3 + pkg/util/hint/hint.go | 2 +- .../casetest/rule/rule_join_reorder.result | 91 ++++++++----------- 9 files changed, 119 insertions(+), 60 deletions(-) diff --git a/pkg/planner/core/casetest/hint/BUILD.bazel b/pkg/planner/core/casetest/hint/BUILD.bazel index 9db40cf4873e4..cf2c5aff0e10b 100644 --- a/pkg/planner/core/casetest/hint/BUILD.bazel +++ b/pkg/planner/core/casetest/hint/BUILD.bazel @@ -9,7 +9,7 @@ go_test( ], data = glob(["testdata/**"]), flaky = True, - shard_count = 6, + shard_count = 7, deps = [ "//pkg/config", "//pkg/domain", diff --git a/pkg/planner/core/casetest/hint/hint_test.go b/pkg/planner/core/casetest/hint/hint_test.go index d62bd7d59777f..98916fa3383d6 100644 --- a/pkg/planner/core/casetest/hint/hint_test.go +++ b/pkg/planner/core/casetest/hint/hint_test.go @@ -340,3 +340,29 @@ func TestOptimizeHintOnPartitionTable(t *testing.T) { tk.MustQuery("SELECT /*+ MAX_EXECUTION_TIME(10), dtc(name=tt) unknow(t1,t2) */ SLEEP(5)").Check(testkit.Rows("0")) require.Len(t, tk.Session().GetSessionVars().StmtCtx.GetWarnings(), 2) } + +func TestHints(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t1 (a int);") + tk.MustExec("create table t2 (a int);") + tk.MustExec("create table t3 (a int);") + var input []string + var output []struct { + SQL string + Plan []string + Warn []string + } + integrationSuiteData := GetIntegrationSuiteData() + integrationSuiteData.LoadTestCases(t, &input, &output) + for i, tt := range input { + testdata.OnRecord(func() { + output[i].SQL = tt + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows()) + output[i].Warn = testdata.ConvertRowsToStrings(tk.MustQuery("show warnings").Rows()) + }) + tk.MustQuery("explain format = 'brief' " + tt).Check(testkit.Rows(output[i].Plan...)) + tk.MustQuery("show warnings").Check(testkit.Rows(output[i].Warn...)) + } +} diff --git a/pkg/planner/core/casetest/hint/testdata/integration_suite_in.json b/pkg/planner/core/casetest/hint/testdata/integration_suite_in.json index 9959c3a7ca666..9edca6deacc28 100644 --- a/pkg/planner/core/casetest/hint/testdata/integration_suite_in.json +++ b/pkg/planner/core/casetest/hint/testdata/integration_suite_in.json @@ -180,5 +180,11 @@ "explain format = 'brief' select /*+ use_index(t, idx)*/ * from t", "explain format = 'brief' select /*+ use_index(t)*/ * from t" ] + }, + { + "name": "TestHints", + "cases": [ + "select * from t1, t2, t3 union all select /*+ leading(t3, t2) */ * from t1, t2, t3 union all select * from t1, t2, t3" + ] } ] diff --git a/pkg/planner/core/casetest/hint/testdata/integration_suite_out.json b/pkg/planner/core/casetest/hint/testdata/integration_suite_out.json index 369189e4531db..471b39747cf4a 100644 --- a/pkg/planner/core/casetest/hint/testdata/integration_suite_out.json +++ b/pkg/planner/core/casetest/hint/testdata/integration_suite_out.json @@ -325,7 +325,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" ], "Warn": [ - "[planner:1815]We can only use one leading hint at most, when multiple leading hints are used, all leading hints will be invalid" + "[planner:1815]leading hint is inapplicable, check if the leading hint table is valid" ] }, { @@ -347,7 +347,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" ], "Warn": [ - "[planner:1815]We can only use one leading hint at most, when multiple leading hints are used, all leading hints will be invalid" + "[planner:1815]leading hint is inapplicable, check if the leading hint table is valid" ] }, { @@ -1862,5 +1862,44 @@ "Warn": null } ] + }, + { + "Name": "TestHints", + "Cases": [ + { + "SQL": "select * from t1, t2, t3 union all select /*+ leading(t3, t2) */ * from t1, t2, t3 union all select * from t1, t2, t3", + "Plan": [ + "Union 3000000000000.00 root ", + "├─HashJoin 1000000000000.00 root CARTESIAN inner join", + "│ ├─TableReader(Build) 10000.00 root data:TableFullScan", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "│ └─HashJoin(Probe) 100000000.00 root CARTESIAN inner join", + "│ ├─TableReader(Build) 10000.00 root data:TableFullScan", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 10000.00 root data:TableFullScan", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "├─Projection 1000000000000.00 root test.t1.a->Column#19, test.t2.a->Column#20, test.t3.a->Column#21", + "│ └─HashJoin 1000000000000.00 root CARTESIAN inner join", + "│ ├─TableReader(Build) 10000.00 root data:TableFullScan", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ └─HashJoin(Probe) 100000000.00 root CARTESIAN inner join", + "│ ├─TableReader(Build) 10000.00 root data:TableFullScan", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 10000.00 root data:TableFullScan", + "│ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "└─HashJoin 1000000000000.00 root CARTESIAN inner join", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + " └─HashJoin(Probe) 100000000.00 root CARTESIAN inner join", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + " └─TableReader(Probe) 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Warn": [ + "Warning 1815 leading hint is inapplicable, check if the leading hint table has join conditions with other tables" + ] + } + ] } ] diff --git a/pkg/planner/core/logical_plan_builder.go b/pkg/planner/core/logical_plan_builder.go index 364304800faf2..2eed4cbac408b 100644 --- a/pkg/planner/core/logical_plan_builder.go +++ b/pkg/planner/core/logical_plan_builder.go @@ -4114,7 +4114,7 @@ func (b *PlanBuilder) pushTableHints(hints []*ast.TableOptimizerHint, currentLev b.ctx.GetSessionVars().StmtCtx.AppendWarning(ErrInternal.FastGen("We can only use the straight_join hint, when we use the leading hint and straight_join hint at the same time, all leading hints will be invalid")) } } - b.tableHintInfo = append(b.tableHintInfo, h.TableHintInfo{ + b.tableHintInfo = append(b.tableHintInfo, &h.TableHintInfo{ SortMergeJoinTables: sortMergeTables, BroadcastJoinTables: bcTables, ShuffleJoinTables: shuffleJoinTables, @@ -4157,7 +4157,7 @@ func (b *PlanBuilder) TableHints() *h.TableHintInfo { if len(b.tableHintInfo) == 0 { return nil } - return &(b.tableHintInfo[len(b.tableHintInfo)-1]) + return b.tableHintInfo[len(b.tableHintInfo)-1] } func (b *PlanBuilder) buildSelect(ctx context.Context, sel *ast.SelectStmt) (p LogicalPlan, err error) { diff --git a/pkg/planner/core/planbuilder.go b/pkg/planner/core/planbuilder.go index d32242e4bd2c8..5fe1d9f8081bd 100644 --- a/pkg/planner/core/planbuilder.go +++ b/pkg/planner/core/planbuilder.go @@ -210,7 +210,7 @@ type PlanBuilder struct { colMapper map[*ast.ColumnNameExpr]int // visitInfo is used for privilege check. visitInfo []visitInfo - tableHintInfo []hint.TableHintInfo + tableHintInfo []*hint.TableHintInfo // optFlag indicates the flags of the optimizer rules. optFlag uint64 // capFlag indicates the capability flags. diff --git a/pkg/planner/core/rule_join_reorder_greedy.go b/pkg/planner/core/rule_join_reorder_greedy.go index 38ce9e66d21b9..0e39c492c0d3a 100644 --- a/pkg/planner/core/rule_join_reorder_greedy.go +++ b/pkg/planner/core/rule_join_reorder_greedy.go @@ -79,6 +79,9 @@ func (s *joinReorderGreedySolver) solve(joinNodePlans []LogicalPlan, tracer *joi // Getting here means that there is no join condition between the table used in the leading hint and other tables // For example: select /*+ leading(t3) */ * from t1 join t2 on t1.a=t2.a cross join t3 // We can not let table t3 join first. + // TODO(hawkingrei): we find the problem in the TestHint. + // `select * from t1, t2, t3 union all select /*+ leading(t3, t2) */ * from t1, t2, t3 union all select * from t1, t2, t3` + // this sql should not return the warning. but It will not affect the result. so we will fix it as soon as possible. s.ctx.GetSessionVars().StmtCtx.AppendWarning(ErrInternal.FastGen("leading hint is inapplicable, check if the leading hint table has join conditions with other tables")) } cartesianGroup = append(cartesianGroup, newNode.p) diff --git a/pkg/util/hint/hint.go b/pkg/util/hint/hint.go index d7108d6bca0d3..bd6baf2bd2063 100644 --- a/pkg/util/hint/hint.go +++ b/pkg/util/hint/hint.go @@ -567,7 +567,7 @@ var ( ) // CollectUnmatchedHintWarnings collects warnings for unmatched hints from this TableHintInfo. -func CollectUnmatchedHintWarnings(hintInfo TableHintInfo) (warnings []error) { +func CollectUnmatchedHintWarnings(hintInfo *TableHintInfo) (warnings []error) { warnings = append(warnings, collectUnmatchedIndexHintWarning(hintInfo.IndexHintList, false)...) warnings = append(warnings, collectUnmatchedIndexHintWarning(hintInfo.IndexMergeHintList, true)...) warnings = append(warnings, collectUnmatchedJoinHintWarning(HintINLJ, TiDBIndexNestedLoopJoin, hintInfo.IndexNestedLoopJoinTables.INLJTables)...) diff --git a/tests/integrationtest/r/planner/core/casetest/rule/rule_join_reorder.result b/tests/integrationtest/r/planner/core/casetest/rule/rule_join_reorder.result index 5cf778d646009..a9135cc00da33 100644 --- a/tests/integrationtest/r/planner/core/casetest/rule/rule_join_reorder.result +++ b/tests/integrationtest/r/planner/core/casetest/rule/rule_join_reorder.result @@ -5468,24 +5468,19 @@ IndexMergeJoin 4.69 root inner join, inner:Projection, outer key:planner__core_ └─TableRowIDScan(Probe) 4.69 cop[tikv] table:t2 keep order:false, stats:pseudo explain format = 'brief' select /*+ leading(t2, t3@sel_2) */ * from t1 join t2 on t1.a=t2.a where t1.a in (select t3.a from t3); id estRows task access object operator info -IndexMergeJoin 4.69 root inner join, inner:Projection, outer key:planner__core__casetest__rule__rule_join_reorder.t1.a, inner key:planner__core__casetest__rule__rule_join_reorder.t2.a -├─IndexMergeJoin(Build) 3.75 root inner join, inner:Projection, outer key:planner__core__casetest__rule__rule_join_reorder.t3.a, inner key:planner__core__casetest__rule__rule_join_reorder.t1.a -│ ├─StreamAgg(Build) 3.00 root group by:planner__core__casetest__rule__rule_join_reorder.t3.a, funcs:firstrow(planner__core__casetest__rule__rule_join_reorder.t3.a)->planner__core__casetest__rule__rule_join_reorder.t3.a -│ │ └─IndexReader 3.00 root index:StreamAgg -│ │ └─StreamAgg 3.00 cop[tikv] group by:planner__core__casetest__rule__rule_join_reorder.t3.a, -│ │ └─IndexFullScan 3.00 cop[tikv] table:t3, index:a(a) keep order:true -│ └─Projection(Probe) 3.75 root planner__core__casetest__rule__rule_join_reorder.t1.a, planner__core__casetest__rule__rule_join_reorder.t1.b -│ └─IndexLookUp 3.75 root -│ ├─Selection(Build) 3.75 cop[tikv] not(isnull(planner__core__casetest__rule__rule_join_reorder.t1.a)) -│ │ └─IndexRangeScan 3.75 cop[tikv] table:t1, index:a(a) range: decided by [eq(planner__core__casetest__rule__rule_join_reorder.t1.a, planner__core__casetest__rule__rule_join_reorder.t3.a)], keep order:true, stats:pseudo -│ └─TableRowIDScan(Probe) 3.75 cop[tikv] table:t1 keep order:false, stats:pseudo -└─Projection(Probe) 4.69 root planner__core__casetest__rule__rule_join_reorder.t2.a, planner__core__casetest__rule__rule_join_reorder.t2.b - └─IndexLookUp 4.69 root - ├─Selection(Build) 4.69 cop[tikv] not(isnull(planner__core__casetest__rule__rule_join_reorder.t2.a)) - │ └─IndexRangeScan 4.69 cop[tikv] table:t2, index:a(a) range: decided by [eq(planner__core__casetest__rule__rule_join_reorder.t2.a, planner__core__casetest__rule__rule_join_reorder.t1.a)], keep order:true, stats:pseudo - └─TableRowIDScan(Probe) 4.69 cop[tikv] table:t2 keep order:false, stats:pseudo -Level Code Message -Warning 1815 We can only use one leading hint at most, when multiple leading hints are used, all leading hints will be invalid +Projection 37462.50 root planner__core__casetest__rule__rule_join_reorder.t1.a, planner__core__casetest__rule__rule_join_reorder.t1.b, planner__core__casetest__rule__rule_join_reorder.t2.a, planner__core__casetest__rule__rule_join_reorder.t2.b +└─HashJoin 37462.50 root inner join, equal:[eq(planner__core__casetest__rule__rule_join_reorder.t2.a, planner__core__casetest__rule__rule_join_reorder.t1.a) eq(planner__core__casetest__rule__rule_join_reorder.t3.a, planner__core__casetest__rule__rule_join_reorder.t1.a)] + ├─TableReader(Build) 9990.00 root data:Selection + │ └─Selection 9990.00 cop[tikv] not(isnull(planner__core__casetest__rule__rule_join_reorder.t1.a)) + │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo + └─HashJoin(Probe) 29970.00 root CARTESIAN inner join + ├─StreamAgg(Build) 3.00 root group by:planner__core__casetest__rule__rule_join_reorder.t3.a, funcs:firstrow(planner__core__casetest__rule__rule_join_reorder.t3.a)->planner__core__casetest__rule__rule_join_reorder.t3.a + │ └─IndexReader 3.00 root index:StreamAgg + │ └─StreamAgg 3.00 cop[tikv] group by:planner__core__casetest__rule__rule_join_reorder.t3.a, + │ └─IndexFullScan 3.00 cop[tikv] table:t3, index:a(a) keep order:true + └─TableReader(Probe) 9990.00 root data:Selection + └─Selection 9990.00 cop[tikv] not(isnull(planner__core__casetest__rule__rule_join_reorder.t2.a)) + └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo explain format = 'brief' select /*+ leading(t1, t3@sel_2) */ * from t1 join t2 on t1.a=t2.a where t1.a in (select t3.a from t3); id estRows task access object operator info IndexMergeJoin 4.69 root inner join, inner:Projection, outer key:planner__core__casetest__rule__rule_join_reorder.t1.a, inner key:planner__core__casetest__rule__rule_join_reorder.t2.a @@ -5504,28 +5499,21 @@ IndexMergeJoin 4.69 root inner join, inner:Projection, outer key:planner__core_ ├─Selection(Build) 4.69 cop[tikv] not(isnull(planner__core__casetest__rule__rule_join_reorder.t2.a)) │ └─IndexRangeScan 4.69 cop[tikv] table:t2, index:a(a) range: decided by [eq(planner__core__casetest__rule__rule_join_reorder.t2.a, planner__core__casetest__rule__rule_join_reorder.t1.a)], keep order:true, stats:pseudo └─TableRowIDScan(Probe) 4.69 cop[tikv] table:t2 keep order:false, stats:pseudo -Level Code Message -Warning 1815 We can only use one leading hint at most, when multiple leading hints are used, all leading hints will be invalid explain format = 'brief' select /*+ leading(t3@sel_2, t2) */ * from t1 join t2 on t1.a=t2.a where t1.a in (select t3.a from t3); id estRows task access object operator info -IndexMergeJoin 4.69 root inner join, inner:Projection, outer key:planner__core__casetest__rule__rule_join_reorder.t1.a, inner key:planner__core__casetest__rule__rule_join_reorder.t2.a -├─IndexMergeJoin(Build) 3.75 root inner join, inner:Projection, outer key:planner__core__casetest__rule__rule_join_reorder.t3.a, inner key:planner__core__casetest__rule__rule_join_reorder.t1.a -│ ├─StreamAgg(Build) 3.00 root group by:planner__core__casetest__rule__rule_join_reorder.t3.a, funcs:firstrow(planner__core__casetest__rule__rule_join_reorder.t3.a)->planner__core__casetest__rule__rule_join_reorder.t3.a -│ │ └─IndexReader 3.00 root index:StreamAgg -│ │ └─StreamAgg 3.00 cop[tikv] group by:planner__core__casetest__rule__rule_join_reorder.t3.a, -│ │ └─IndexFullScan 3.00 cop[tikv] table:t3, index:a(a) keep order:true -│ └─Projection(Probe) 3.75 root planner__core__casetest__rule__rule_join_reorder.t1.a, planner__core__casetest__rule__rule_join_reorder.t1.b -│ └─IndexLookUp 3.75 root -│ ├─Selection(Build) 3.75 cop[tikv] not(isnull(planner__core__casetest__rule__rule_join_reorder.t1.a)) -│ │ └─IndexRangeScan 3.75 cop[tikv] table:t1, index:a(a) range: decided by [eq(planner__core__casetest__rule__rule_join_reorder.t1.a, planner__core__casetest__rule__rule_join_reorder.t3.a)], keep order:true, stats:pseudo -│ └─TableRowIDScan(Probe) 3.75 cop[tikv] table:t1 keep order:false, stats:pseudo -└─Projection(Probe) 4.69 root planner__core__casetest__rule__rule_join_reorder.t2.a, planner__core__casetest__rule__rule_join_reorder.t2.b - └─IndexLookUp 4.69 root - ├─Selection(Build) 4.69 cop[tikv] not(isnull(planner__core__casetest__rule__rule_join_reorder.t2.a)) - │ └─IndexRangeScan 4.69 cop[tikv] table:t2, index:a(a) range: decided by [eq(planner__core__casetest__rule__rule_join_reorder.t2.a, planner__core__casetest__rule__rule_join_reorder.t1.a)], keep order:true, stats:pseudo - └─TableRowIDScan(Probe) 4.69 cop[tikv] table:t2 keep order:false, stats:pseudo -Level Code Message -Warning 1815 We can only use one leading hint at most, when multiple leading hints are used, all leading hints will be invalid +Projection 37462.50 root planner__core__casetest__rule__rule_join_reorder.t1.a, planner__core__casetest__rule__rule_join_reorder.t1.b, planner__core__casetest__rule__rule_join_reorder.t2.a, planner__core__casetest__rule__rule_join_reorder.t2.b +└─HashJoin 37462.50 root inner join, equal:[eq(planner__core__casetest__rule__rule_join_reorder.t2.a, planner__core__casetest__rule__rule_join_reorder.t1.a) eq(planner__core__casetest__rule__rule_join_reorder.t3.a, planner__core__casetest__rule__rule_join_reorder.t1.a)] + ├─TableReader(Build) 9990.00 root data:Selection + │ └─Selection 9990.00 cop[tikv] not(isnull(planner__core__casetest__rule__rule_join_reorder.t1.a)) + │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo + └─HashJoin(Probe) 29970.00 root CARTESIAN inner join + ├─StreamAgg(Build) 3.00 root group by:planner__core__casetest__rule__rule_join_reorder.t3.a, funcs:firstrow(planner__core__casetest__rule__rule_join_reorder.t3.a)->planner__core__casetest__rule__rule_join_reorder.t3.a + │ └─IndexReader 3.00 root index:StreamAgg + │ └─StreamAgg 3.00 cop[tikv] group by:planner__core__casetest__rule__rule_join_reorder.t3.a, + │ └─IndexFullScan 3.00 cop[tikv] table:t3, index:a(a) keep order:true + └─TableReader(Probe) 9990.00 root data:Selection + └─Selection 9990.00 cop[tikv] not(isnull(planner__core__casetest__rule__rule_join_reorder.t2.a)) + └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo explain format = 'brief' select /*+ leading(t3@sel_2, t1) */ * from t1 join t2 on t1.a=t2.a where t1.a in (select t3.a from t3); id estRows task access object operator info IndexMergeJoin 4.69 root inner join, inner:Projection, outer key:planner__core__casetest__rule__rule_join_reorder.t1.a, inner key:planner__core__casetest__rule__rule_join_reorder.t2.a @@ -5544,8 +5532,6 @@ IndexMergeJoin 4.69 root inner join, inner:Projection, outer key:planner__core_ ├─Selection(Build) 4.69 cop[tikv] not(isnull(planner__core__casetest__rule__rule_join_reorder.t2.a)) │ └─IndexRangeScan 4.69 cop[tikv] table:t2, index:a(a) range: decided by [eq(planner__core__casetest__rule__rule_join_reorder.t2.a, planner__core__casetest__rule__rule_join_reorder.t1.a)], keep order:true, stats:pseudo └─TableRowIDScan(Probe) 4.69 cop[tikv] table:t2 keep order:false, stats:pseudo -Level Code Message -Warning 1815 We can only use one leading hint at most, when multiple leading hints are used, all leading hints will be invalid explain format = 'brief' select /*+ leading(t4) */ * from t1 join t2 on t1.a=t2.a join t4 on t1.b = t4.b where t1.a not in (select t3.a from t3); id estRows task access object operator info HashJoin 12475.01 root Null-aware anti semi join, equal:[eq(planner__core__casetest__rule__rule_join_reorder.t1.a, planner__core__casetest__rule__rule_join_reorder.t3.a)] @@ -7157,20 +7143,19 @@ HashJoin 12487.50 root left outer join, equal:[eq(planner__core__casetest__rule └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo explain format = 'brief' select /*+ leading(t2, t3@sel_2) */ * from t1 join t2 on t1.a=t2.a where t1.a in (select t3.a from t3); id estRows task access object operator info -HashJoin 12487.50 root inner join, equal:[eq(planner__core__casetest__rule__rule_join_reorder.t1.a, planner__core__casetest__rule__rule_join_reorder.t3.a)] -├─StreamAgg(Build) 7992.00 root group by:planner__core__casetest__rule__rule_join_reorder.t3.a, funcs:firstrow(planner__core__casetest__rule__rule_join_reorder.t3.a)->planner__core__casetest__rule__rule_join_reorder.t3.a -│ └─IndexReader 7992.00 root index:StreamAgg -│ └─StreamAgg 7992.00 cop[tikv] group by:planner__core__casetest__rule__rule_join_reorder.t3.a, -│ └─IndexFullScan 9990.00 cop[tikv] table:t3, index:a(a) keep order:true, stats:pseudo -└─HashJoin(Probe) 12487.50 root inner join, equal:[eq(planner__core__casetest__rule__rule_join_reorder.t1.a, planner__core__casetest__rule__rule_join_reorder.t2.a)] +Projection 99800100.00 root planner__core__casetest__rule__rule_join_reorder.t1.a, planner__core__casetest__rule__rule_join_reorder.t1.b, planner__core__casetest__rule__rule_join_reorder.t2.a, planner__core__casetest__rule__rule_join_reorder.t2.b +└─HashJoin 99800100.00 root inner join, equal:[eq(planner__core__casetest__rule__rule_join_reorder.t2.a, planner__core__casetest__rule__rule_join_reorder.t1.a) eq(planner__core__casetest__rule__rule_join_reorder.t3.a, planner__core__casetest__rule__rule_join_reorder.t1.a)] ├─TableReader(Build) 9990.00 root data:Selection - │ └─Selection 9990.00 cop[tikv] not(isnull(planner__core__casetest__rule__rule_join_reorder.t2.a)) - │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo - └─TableReader(Probe) 9990.00 root data:Selection - └─Selection 9990.00 cop[tikv] not(isnull(planner__core__casetest__rule__rule_join_reorder.t1.a)) - └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo -Level Code Message -Warning 1815 We can only use one leading hint at most, when multiple leading hints are used, all leading hints will be invalid + │ └─Selection 9990.00 cop[tikv] not(isnull(planner__core__casetest__rule__rule_join_reorder.t1.a)) + │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo + └─HashJoin(Probe) 79840080.00 root CARTESIAN inner join + ├─StreamAgg(Build) 7992.00 root group by:planner__core__casetest__rule__rule_join_reorder.t3.a, funcs:firstrow(planner__core__casetest__rule__rule_join_reorder.t3.a)->planner__core__casetest__rule__rule_join_reorder.t3.a + │ └─IndexReader 7992.00 root index:StreamAgg + │ └─StreamAgg 7992.00 cop[tikv] group by:planner__core__casetest__rule__rule_join_reorder.t3.a, + │ └─IndexFullScan 9990.00 cop[tikv] table:t3, index:a(a) keep order:true, stats:pseudo + └─TableReader(Probe) 9990.00 root data:Selection + └─Selection 9990.00 cop[tikv] not(isnull(planner__core__casetest__rule__rule_join_reorder.t2.a)) + └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo explain format = 'brief' select /*+ leading(t4) */ * from t1 left join t2 on t1.a=t2.a right join t4 on t1.b = t4.b where t1.a not in (select t3.a from t3); id estRows task access object operator info HashJoin 12487.50 root Null-aware anti semi join, equal:[eq(planner__core__casetest__rule__rule_join_reorder.t1.a, planner__core__casetest__rule__rule_join_reorder.t3.a)]