From 1b13108cd5d9a08b98887320171ed54f3ef5e6d6 Mon Sep 17 00:00:00 2001 From: Ti Chi Robot Date: Fri, 12 Jan 2024 12:10:55 +0800 Subject: [PATCH] planner: fix leading hint cannot take effect in UNION ALL statements (#50277) (#50322) close pingcap/tidb#50067 --- .../testdata/integration_suite_out.json | 4 +- .../testdata/join_reorder_suite_out.json | 98 ++++++++----------- planner/core/logical_plan_builder.go | 4 +- planner/core/planbuilder.go | 2 +- planner/core/rule_join_reorder_greedy.go | 3 + 5 files changed, 51 insertions(+), 60 deletions(-) diff --git a/planner/core/casetest/testdata/integration_suite_out.json b/planner/core/casetest/testdata/integration_suite_out.json index 7c610c3232bbf..0478934c41793 100644 --- a/planner/core/casetest/testdata/integration_suite_out.json +++ b/planner/core/casetest/testdata/integration_suite_out.json @@ -6134,7 +6134,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" ] }, { @@ -6155,7 +6155,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" ] }, { diff --git a/planner/core/casetest/testdata/join_reorder_suite_out.json b/planner/core/casetest/testdata/join_reorder_suite_out.json index 860d0aa487325..6bdf1de502b4d 100644 --- a/planner/core/casetest/testdata/join_reorder_suite_out.json +++ b/planner/core/casetest/testdata/join_reorder_suite_out.json @@ -922,7 +922,6 @@ } ] }, - { "Name": "TestNoIndexJoinHint", "Cases": [ @@ -7970,24 +7969,21 @@ { "SQL": "select /*+ leading(t2, t3@sel_2) */ * from t1 join t2 on t1.a=t2.a where t1.a in (select t3.a from t3)", "Plan": [ - "IndexHashJoin 4.69 root inner join, inner:IndexLookUp, outer key:test.t1.a, inner key:test.t2.a, equal cond:eq(test.t1.a, test.t2.a)", - "├─IndexHashJoin(Build) 3.75 root inner join, inner:IndexLookUp, outer key:test.t3.a, inner key:test.t1.a, equal cond:eq(test.t3.a, test.t1.a)", - "│ ├─StreamAgg(Build) 3.00 root group by:test.t3.a, funcs:firstrow(test.t3.a)->test.t3.a", - "│ │ └─IndexReader 3.00 root index:StreamAgg", - "│ │ └─StreamAgg 3.00 cop[tikv] group by:test.t3.a, ", - "│ │ └─IndexFullScan 3.00 cop[tikv] table:t3, index:a(a) keep order:true", - "│ └─IndexLookUp(Probe) 3.75 root ", - "│ ├─Selection(Build) 3.75 cop[tikv] not(isnull(test.t1.a))", - "│ │ └─IndexRangeScan 3.75 cop[tikv] table:t1, index:a(a) range: decided by [eq(test.t1.a, test.t3.a)], keep order:false, stats:pseudo", - "│ └─TableRowIDScan(Probe) 3.75 cop[tikv] table:t1 keep order:false, stats:pseudo", - "└─IndexLookUp(Probe) 4.69 root ", - " ├─Selection(Build) 4.69 cop[tikv] not(isnull(test.t2.a))", - " │ └─IndexRangeScan 4.69 cop[tikv] table:t2, index:a(a) range: decided by [eq(test.t2.a, test.t1.a)], keep order:false, stats:pseudo", - " └─TableRowIDScan(Probe) 4.69 cop[tikv] table:t2 keep order:false, stats:pseudo" + "Projection 37462.50 root test.t1.a, test.t1.b, test.t2.a, test.t2.b", + "└─HashJoin 37462.50 root inner join, equal:[eq(test.t2.a, test.t1.a) eq(test.t3.a, test.t1.a)]", + " ├─TableReader(Build) 9990.00 root data:Selection", + " │ └─Selection 9990.00 cop[tikv] not(isnull(test.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:test.t3.a, funcs:firstrow(test.t3.a)->test.t3.a", + " │ └─IndexReader 3.00 root index:StreamAgg", + " │ └─StreamAgg 3.00 cop[tikv] group by:test.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(test.t2.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" ], - "Warning": [ - "Warning 1815 We can only use one leading hint at most, when multiple leading hints are used, all leading hints will be invalid" - ] + "Warning": null }, { "SQL": "select /*+ leading(t1, t3@sel_2) */ * from t1 join t2 on t1.a=t2.a where t1.a in (select t3.a from t3)", @@ -8007,31 +8003,26 @@ " │ └─IndexRangeScan 4.69 cop[tikv] table:t2, index:a(a) range: decided by [eq(test.t2.a, test.t1.a)], keep order:false, stats:pseudo", " └─TableRowIDScan(Probe) 4.69 cop[tikv] table:t2 keep order:false, stats:pseudo" ], - "Warning": [ - "Warning 1815 We can only use one leading hint at most, when multiple leading hints are used, all leading hints will be invalid" - ] + "Warning": null }, { "SQL": "select /*+ leading(t3@sel_2, t2) */ * from t1 join t2 on t1.a=t2.a where t1.a in (select t3.a from t3)", "Plan": [ - "IndexHashJoin 4.69 root inner join, inner:IndexLookUp, outer key:test.t1.a, inner key:test.t2.a, equal cond:eq(test.t1.a, test.t2.a)", - "├─IndexHashJoin(Build) 3.75 root inner join, inner:IndexLookUp, outer key:test.t3.a, inner key:test.t1.a, equal cond:eq(test.t3.a, test.t1.a)", - "│ ├─StreamAgg(Build) 3.00 root group by:test.t3.a, funcs:firstrow(test.t3.a)->test.t3.a", - "│ │ └─IndexReader 3.00 root index:StreamAgg", - "│ │ └─StreamAgg 3.00 cop[tikv] group by:test.t3.a, ", - "│ │ └─IndexFullScan 3.00 cop[tikv] table:t3, index:a(a) keep order:true", - "│ └─IndexLookUp(Probe) 3.75 root ", - "│ ├─Selection(Build) 3.75 cop[tikv] not(isnull(test.t1.a))", - "│ │ └─IndexRangeScan 3.75 cop[tikv] table:t1, index:a(a) range: decided by [eq(test.t1.a, test.t3.a)], keep order:false, stats:pseudo", - "│ └─TableRowIDScan(Probe) 3.75 cop[tikv] table:t1 keep order:false, stats:pseudo", - "└─IndexLookUp(Probe) 4.69 root ", - " ├─Selection(Build) 4.69 cop[tikv] not(isnull(test.t2.a))", - " │ └─IndexRangeScan 4.69 cop[tikv] table:t2, index:a(a) range: decided by [eq(test.t2.a, test.t1.a)], keep order:false, stats:pseudo", - " └─TableRowIDScan(Probe) 4.69 cop[tikv] table:t2 keep order:false, stats:pseudo" + "Projection 37462.50 root test.t1.a, test.t1.b, test.t2.a, test.t2.b", + "└─HashJoin 37462.50 root inner join, equal:[eq(test.t2.a, test.t1.a) eq(test.t3.a, test.t1.a)]", + " ├─TableReader(Build) 9990.00 root data:Selection", + " │ └─Selection 9990.00 cop[tikv] not(isnull(test.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:test.t3.a, funcs:firstrow(test.t3.a)->test.t3.a", + " │ └─IndexReader 3.00 root index:StreamAgg", + " │ └─StreamAgg 3.00 cop[tikv] group by:test.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(test.t2.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" ], - "Warning": [ - "Warning 1815 We can only use one leading hint at most, when multiple leading hints are used, all leading hints will be invalid" - ] + "Warning": null }, { "SQL": "select /*+ leading(t3@sel_2, t1) */ * from t1 join t2 on t1.a=t2.a where t1.a in (select t3.a from t3)", @@ -8051,9 +8042,7 @@ " │ └─IndexRangeScan 4.69 cop[tikv] table:t2, index:a(a) range: decided by [eq(test.t2.a, test.t1.a)], keep order:false, stats:pseudo", " └─TableRowIDScan(Probe) 4.69 cop[tikv] table:t2 keep order:false, stats:pseudo" ], - "Warning": [ - "Warning 1815 We can only use one leading hint at most, when multiple leading hints are used, all leading hints will be invalid" - ] + "Warning": null }, { "SQL": "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)", @@ -10036,22 +10025,21 @@ { "SQL": "select /*+ leading(t2, t3@sel_2) */ * from t1 join t2 on t1.a=t2.a where t1.a in (select t3.a from t3)", "Plan": [ - "HashJoin 12487.50 root inner join, equal:[eq(test.t1.a, test.t3.a)]", - "├─StreamAgg(Build) 7992.00 root group by:test.t3.a, funcs:firstrow(test.t3.a)->test.t3.a", - "│ └─IndexReader 7992.00 root index:StreamAgg", - "│ └─StreamAgg 7992.00 cop[tikv] group by:test.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(test.t1.a, test.t2.a)]", + "Projection 99800100.00 root test.t1.a, test.t1.b, test.t2.a, test.t2.b", + "└─HashJoin 99800100.00 root inner join, equal:[eq(test.t2.a, test.t1.a) eq(test.t3.a, test.t1.a)]", " ├─TableReader(Build) 9990.00 root data:Selection", - " │ └─Selection 9990.00 cop[tikv] not(isnull(test.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(test.t1.a))", - " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + " │ └─Selection 9990.00 cop[tikv] not(isnull(test.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:test.t3.a, funcs:firstrow(test.t3.a)->test.t3.a", + " │ └─IndexReader 7992.00 root index:StreamAgg", + " │ └─StreamAgg 7992.00 cop[tikv] group by:test.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(test.t2.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" ], - "Warning": [ - "Warning 1815 We can only use one leading hint at most, when multiple leading hints are used, all leading hints will be invalid" - ] + "Warning": null }, { "SQL": "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)", diff --git a/planner/core/logical_plan_builder.go b/planner/core/logical_plan_builder.go index 29a369f60695e..4d5159298bb3c 100644 --- a/planner/core/logical_plan_builder.go +++ b/planner/core/logical_plan_builder.go @@ -3933,7 +3933,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, tableHintInfo{ + b.tableHintInfo = append(b.tableHintInfo, &tableHintInfo{ sortMergeJoinTables: sortMergeTables, broadcastJoinTables: bcTables, shuffleJoinTables: shuffleJoinTables, @@ -4032,7 +4032,7 @@ func (b *PlanBuilder) TableHints() *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/planner/core/planbuilder.go b/planner/core/planbuilder.go index 97cbd8ae284d4..7ec1627e9f189 100644 --- a/planner/core/planbuilder.go +++ b/planner/core/planbuilder.go @@ -528,7 +528,7 @@ type PlanBuilder struct { colMapper map[*ast.ColumnNameExpr]int // visitInfo is used for privilege check. visitInfo []visitInfo - tableHintInfo []tableHintInfo + tableHintInfo []*tableHintInfo // optFlag indicates the flags of the optimizer rules. optFlag uint64 // capFlag indicates the capability flags. diff --git a/planner/core/rule_join_reorder_greedy.go b/planner/core/rule_join_reorder_greedy.go index 7bd3faac386cf..325cdb49f447b 100644 --- a/planner/core/rule_join_reorder_greedy.go +++ b/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)