planner: support the view hint(part-2) (#39280)

ref pingcap/tidb#37887
This commit is contained in:
Chengpeng Yan
2022-11-29 19:50:00 +08:00
committed by GitHub
parent 1b15732d11
commit 8a5ccd87d7
6 changed files with 281 additions and 201 deletions

View File

@ -1365,16 +1365,18 @@ func TestViewHintScope(t *testing.T) {
tk.MustExec("use test")
tk.MustExec("set tidb_cost_model_version=2")
tk.MustExec("drop view if exists v, v1, v2, v3")
tk.MustExec("drop table if exists t, t1, t2")
tk.MustExec("drop view if exists v, v1, v2, v3, v4")
tk.MustExec("drop table if exists t, t1, t2, t3, t4")
tk.MustExec("create table t(a int, b int);")
tk.MustExec("create table t1(a int, b int);")
tk.MustExec("create table t2(a int, b int);")
tk.MustExec("create table t3(a int, b int)")
tk.MustExec("create table t4(a int, b int, index idx_a(a), index idx_b(b))")
tk.MustExec("create definer='root'@'localhost' view v as select t.a, t.b from t join (select count(*) as a from t1 join t2 join t3 where t1.b=t2.b and t2.a = t3.a group by t2.a) tt on t.a = tt.a;")
tk.MustExec("create definer='root'@'localhost' view v1 as select t.a, t.b from t join (select count(*) as a from t1 join v on t1.b=v.b group by v.a) tt on t.a = tt.a;")
tk.MustExec("create definer='root'@'localhost' view v2 as select t.a, t.b from t join (select count(*) as a from t1 join v1 on t1.b=v1.b group by v1.a) tt on t.a = tt.a;")
tk.MustExec("create definer='root'@'localhost' view v3 as select /*+ merge_join(t) */ t.a, t.b from t join (select /*+ stream_agg() */ count(*) as a from t1 join v1 on t1.b=v1.b group by v1.a) tt on t.a = tt.a;")
tk.MustExec("create definer='root'@'localhost' view v4 as select * from t4 where a > 2 and b > 3;")
var input []string
var output []struct {
@ -1403,7 +1405,7 @@ func TestViewHintWithBinding(t *testing.T) {
tk.MustExec("use test")
tk.MustExec("set tidb_cost_model_version=2")
tk.MustExec("drop view if exists v, v1")
tk.MustExec("drop table if exists t, t1, t2")
tk.MustExec("drop table if exists t, t1, t2, t3")
tk.MustExec("create table t(a int, b int);")
tk.MustExec("create table t1(a int, b int);")
tk.MustExec("create table t2(a int, b int);")

View File

@ -4438,8 +4438,7 @@ func (b *PlanBuilder) buildDataSource(ctx context.Context, tn *ast.TableName, as
// Because of the nested views, so we should check the left table list in hint when build the data source from the view inside the current view.
currentQBNameMap4View[qbName] = viewQBNameHintTable[1:]
currentViewHints[qbName] = b.hintProcessor.QbHints4View[qbName]
delete(b.hintProcessor.QbNameMap4View, qbName)
delete(b.hintProcessor.QbHints4View, qbName)
b.hintProcessor.QbNameUsed4View[qbName] = struct{}{}
}
}
return b.BuildDataSourceFromView(ctx, dbName, tableInfo, currentQBNameMap4View, currentViewHints)
@ -5042,6 +5041,7 @@ func (b *PlanBuilder) BuildDataSourceFromView(ctx context.Context, dbName model.
hintProcessor.QbNameMap4View = qbNameMap4View
hintProcessor.QbHints4View = viewHints
hintProcessor.QbNameUsed4View = make(map[string]struct{})
hintProcessor.QbHints = currentQbHints
hintProcessor.QbNameMap = currentQbNameMap
@ -5050,6 +5050,7 @@ func (b *PlanBuilder) BuildDataSourceFromView(ctx context.Context, dbName model.
b.hintProcessor = hintProcessor
b.ctx.GetSessionVars().PlannerSelectBlockAsName = make([]ast.HintTable, hintProcessor.MaxSelectStmtOffset()+1)
defer func() {
b.hintProcessor.HandleUnusedViewHints()
b.hintProcessor = originHintProcessor
b.ctx.GetSessionVars().PlannerSelectBlockAsName = originPlannerSelectBlockAsName
}()

View File

@ -667,8 +667,8 @@
// Hint for view v1
"explain format = 'brief' select /*+ qb_name(qb_v1_2, v1@sel_1 .@sel_2), merge_join(t1@qb_v1_2) */ * from v1;",
"explain format = 'brief' select /*+ qb_name(qb_v1_2, v1@sel_1 .@sel_2), merge_join(t1@qb_v1_2), stream_agg(@qb_v1_2), qb_name(qb_v1_1, v1@sel_1 .@sel_1), merge_join(t@qb_v1_1) */ * from v1;",
"explain format = 'brief' select /*+ qb_name(qb_v1_2, v2@sel_1 . v1@sel_1 .@sel_2), merge_join(t1@qb_v1_2) */ * from v2;",
"explain format = 'brief' select /*+ qb_name(qb_v1_2, v2@sel_1 . v1@sel_1 .@sel_2), merge_join(t1@qb_v1_2), stream_agg(@qb_v1_2), qb_name(qb_v1_1, v2@sel_1 . v1@sel_1 .@sel_1), merge_join(t@qb_v1_1) */ * from v2;",
"explain format = 'brief' select /*+ qb_name(qb_v1_2, v2@sel_1 . v1@sel_2 .@sel_2), merge_join(t1@qb_v1_2) */ * from v2;",
"explain format = 'brief' select /*+ qb_name(qb_v1_2, v2@sel_1 . v1@sel_2 .@sel_2), merge_join(t1@qb_v1_2), stream_agg(@qb_v1_2), qb_name(qb_v1_1, v2@sel_1 . v1@sel_2 .@sel_1), merge_join(t@qb_v1_1) */ * from v2;",
// Hint for view v2
"explain format = 'brief' select /*+ qb_name(qb_v2_2, v2@sel_1 .@sel_2), merge_join(t1@qb_v2_2) */ * from v2;",
@ -684,7 +684,6 @@
"explain format = 'brief' select /*+ qb_name(qb_v, v2@sel_1 .v1@sel_2 .v@sel_2 .@sel_2), qb_name(qb_v, v2@sel_1 .v1@sel_2 .v@sel_2 .@sel_1), merge_join(t1@qb_v) */ * from v2;",
// Set the unappeared view name
// TODO: add the warning for the unused the view hints
"explain format = 'brief' select /*+ qb_name(qb_v1_2, v@sel_1 .@sel_2), merge_join(t1@qb_v1_2) */ * from v1;",
"explain format = 'brief' select /*+ qb_name(qb_v1_2, v2@sel_1 . v@sel_1 .@sel_2), merge_join(t1@qb_v1_2) */ * from v2;",
@ -694,18 +693,17 @@
// Tht view hint isn't set in the first query block.
"explain format = 'brief' select * from (select /*+ qb_name(qb_v_2, v@sel_1 .@sel_2), merge_join(t1@qb_v_2) */ * from v) t;",
"explain format = 'brief' select * from (select /*+ qb_name(qb_v_2, v@sel_1 .@sel_2), merge_join(t1@qb_v_2), stream_agg(@qb_v_2), qb_name(qb_v_1, v@sel_1 .@sel1), merge_join(t@qb_v_1) */ * from v) t;",
"explain format = 'brief' select * from (select /*+ qb_name(qb_v_2, v.@sel_2), merge_join(t1@qb_v_2), stream_agg(@qb_v_2), qb_name(qb_v_1, v@sel_1 .@sel1), merge_join(t@qb_v_1) */ * from v) t;",
"explain format = 'brief' select * from (select /*+ qb_name(qb_v_2, v1@sel_1 . v@sel_2 .@sel_2), merge_join(t1@qb_v_2) */ * from v1) t;",
"explain format = 'brief' select * from (select /*+ qb_name(qb_v_2, v1@sel_1 . v@sel_2 .@sel_2), merge_join(t1@qb_v_2), stream_agg(@qb_v_2), qb_name(qb_v_1, v1@sel_1 . v@sel_2 .@sel_1), merge_join(t@qb_v_1) */ * from v1) t;",
"explain format = 'brief' select * from (select /*+ qb_name(qb_v_2, v1.v@sel_2 .@sel_2), merge_join(t1@qb_v_2), stream_agg(@qb_v_2), qb_name(qb_v_1, v1@sel_1 . v@sel_2 .@sel_1), merge_join(t@qb_v_1) */ * from v1) t;",
// TODO: add the warning when the view hints don't set in the first query block
"explain format = 'brief' select /*+ qb_name(qb_v_2, v@sel_1 .@sel_2) */ * from (select /*+ merge_join(t1@qb_v_2) */ * from v) t;",
"explain format = 'brief' select /*+ qb_name(qb_v_2, v@sel_1 .@sel_2), qb_name(qb_v_1, v@sel_1 .@sel1) */ * from (select /*+ merge_join(t1@qb_v_2), stream_agg(@qb_v_2), merge_join(t@qb_v_1) */ * from v) t;",
"explain format = 'brief' select /*+ qb_name(qb_v_2, v1@sel_1 . v@sel_2 .@sel_2) */ * from (select /*+ merge_join(t1@qb_v_2) */ * from v1) t;",
"explain format = 'brief' select /*+ qb_name(qb_v_2, v1@sel_1 . v@sel_2 .@sel_2), qb_name(qb_v_1, v1@sel_1 . v@sel_2 .@sel_1) */ * from (select /*+ merge_join(t1@qb_v_2), stream_agg(@qb_v_2), merge_join(t@qb_v_1) */ * from v1) t;",
"explain format = 'brief' select /*+ qb_name(qb_v_2, v@sel_2 .@sel_2) */ * from (select /*+ merge_join(t1@qb_v_2) */ * from v) t;",
"explain format = 'brief' select /*+ qb_name(qb_v_2, v@sel_2 .@sel_2), qb_name(qb_v_1, v@sel_2 .@sel1) */ * from (select /*+ merge_join(t1@qb_v_2), stream_agg(@qb_v_2), merge_join(t@qb_v_1) */ * from v) t;",
"explain format = 'brief' select /*+ qb_name(qb_v_2, v1@sel_2 . v@sel_2 .@sel_2) */ * from (select /*+ merge_join(t1@qb_v_2) */ * from v1) t;",
"explain format = 'brief' select /*+ qb_name(qb_v_2, v1@sel_2 . v@sel_2 .@sel_2), qb_name(qb_v_1, v1@sel_2 . v@sel_2 .@sel_1) */ * from (select /*+ merge_join(t1@qb_v_2), stream_agg(@qb_v_2), merge_join(t@qb_v_1) */ * from v1) t;",
// Define more tables in one view hint
"explain format = 'brief' select /*+ qb_name(qb_v1_2, v2@sel_1 . v1@sel_1 .@sel_2), qb_name(qb_v1_1, v2@sel_1 . v1@sel_1 .@sel_1), merge_join(t1@qb_v1_2, t@qb_v1_1) */ * from v2;",
"explain format = 'brief' select /*+ qb_name(qb_v1_2, v2. v1@sel_2 .@sel_2), qb_name(qb_v1_1, v2@sel_1 . v1@sel_2 .@sel_1), merge_join(t1@qb_v1_2, t@qb_v1_1), merge_join(t1@qb_v1_2) */ * from v2;",
"explain format = 'brief' select /*+ qb_name(qb_v_2, v2@sel_1 . v1@sel_2 . v@sel_2 .@sel_2), qb_name(qb_v_1, v2@sel_1 . v1@sel_2 . v@sel_2 .@sel_1), merge_join(t1@qb_v_2, t3@qb_v_2) */ * from v2;",
"explain format = 'brief' select /*+ qb_name(qb_v_2, v2@sel_1 . v1@sel_2 . v@sel_2 .@sel_2), qb_name(qb_v_1, v2@sel_1 . v1@sel_2 . v@sel_2 .@sel_1), merge_join(@qb_v_2 t1, t3) */ * from v2;",
@ -721,7 +719,12 @@
// The view contains the hint when creation
"explain format = 'brief' select /*+ qb_name(qb_v3_2, v3@sel_1 .@sel_2), merge_join(t1@qb_v3_2) */ * from v3;",
"explain format = 'brief' select /*+ qb_name(qb_v3_2, v3@sel_1 .@sel_2), merge_join(t1@qb_v3_2), hash_agg(@qb_v3_2), qb_name(qb_v3_1, v3@sel_1 .@sel_1), hash_join(t@qb_v3_1) */ * from v3;"
"explain format = 'brief' select /*+ qb_name(qb_v3_2, v3@sel_1 .@sel_2), merge_join(t1@qb_v3_2), hash_agg(@qb_v3_2), qb_name(qb_v3_1, v3@sel_1 .@sel_1), hash_join(t@qb_v3_1) */ * from v3;",
// The view is in the CTE
"explain with d1 as (\n select a from (\n select a from (\n select /*+ qb_name(qb, v4) use_index(t4@qb, idx_a) */ a from v4 where a < 10\n ) as t0 where a < 9\n ) as t1 where a < 8\n), d2 as (select /*+ qb_name(qb2, v4) use_index(t4@qb2, idx_b) */ a from v4 where b < 10)\n\nselect * from (select * from d1) as t0 join (select * from d2) as t1;",
"explain with d1 as (\n select a from (\n select a from (\n select a from v4 where a < 10\n ) as t0 where a < 9\n ) as t1 where a < 8\n), d2 as (select a from v4 where b < 10)\n\nselect /*+ qb_name(qb, v4@sel_4) use_index(t4@qb, idx_a) qb_name(qb2, v4@sel_5) use_index(t4@qb, idx_b) */ * from (select * from d1) as t0 join (select * from d2) as t1;",
"explain with d1 as (\n select a from (\n select a from (\n select /*+ qb_name(qb, v5) use_index(t4@qb, idx_a) */ a from v4 where a < 10\n ) as t0 where a < 9\n ) as t1 where a < 8\n), d2 as (select /*+ qb_name(qb2, v4) use_index(t4@qb2, idx_b) */ a from v4 where b < 10)\n\nselect * from (select * from d1) as t0 join (select * from d2) as t1;"
]
},
{

View File

@ -4603,28 +4603,30 @@
"Warn": null
},
{
"SQL": "explain format = 'brief' select /*+ qb_name(qb_v1_2, v2@sel_1 . v1@sel_1 .@sel_2), merge_join(t1@qb_v1_2) */ * from v2;",
"SQL": "explain format = 'brief' select /*+ qb_name(qb_v1_2, v2@sel_1 . v1@sel_2 .@sel_2), merge_join(t1@qb_v1_2) */ * from v2;",
"Plan": [
"HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#24)]",
"├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#24",
"│ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#23)]",
"│ ├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#23",
"│ │ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#22)]",
"│ │ ├─HashAgg(Build) 7992.00 root group by:test.t2.a, funcs:count(1)->Column#22",
"│ │ │ └─HashJoin 12487.50 root inner join, equal:[eq(test.t1.b, test.t2.b)]",
"│ │ │ ├─TableReader(Build) 9990.00 root data:Selection",
"│ │ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))",
"│ │ │ │ ─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
"│ │ │ └─TableReader(Probe) 9990.00 root data:Selection",
"│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))",
"│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
"│ │ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]",
"│ │ ├─TableReader(Build) 9990.00 root data:Selection",
"│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))",
"│ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
"│ │ └─TableReader(Probe) 9980.01 root data:Selection",
"│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))",
"│ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo",
"│ │ └─MergeJoin 12475.01 root inner join, left key:test.t1.b, right key:test.t.b",
"│ │ ├─Sort(Build) 9980.01 root test.t.b",
"│ │ │ └─HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#22)]",
"│ │ │ ├─HashAgg(Build) 7992.00 root group by:test.t2.a, funcs:count(1)->Column#22",
"│ │ │ │ └─HashJoin 12487.50 root inner join, equal:[eq(test.t1.b, test.t2.b)]",
"│ │ │ │ ─TableReader(Build) 9990.00 root data:Selection",
"│ │ │ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))",
"│ │ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
"│ │ │ └─TableReader(Probe) 9990.00 root data:Selection",
"│ │ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))",
"│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
"│ │ └─TableReader(Probe) 9980.01 root data:Selection",
"│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))",
"│ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo",
"│ │ └─Sort(Probe) 9990.00 root test.t1.b",
"│ │ └─TableReader 9990.00 root data:Selection",
"│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))",
"│ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
"│ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]",
"│ ├─TableReader(Build) 9990.00 root data:Selection",
"│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))",
@ -4639,35 +4641,40 @@
"Warn": null
},
{
"SQL": "explain format = 'brief' select /*+ qb_name(qb_v1_2, v2@sel_1 . v1@sel_1 .@sel_2), merge_join(t1@qb_v1_2), stream_agg(@qb_v1_2), qb_name(qb_v1_1, v2@sel_1 . v1@sel_1 .@sel_1), merge_join(t@qb_v1_1) */ * from v2;",
"SQL": "explain format = 'brief' select /*+ qb_name(qb_v1_2, v2@sel_1 . v1@sel_2 .@sel_2), merge_join(t1@qb_v1_2), stream_agg(@qb_v1_2), qb_name(qb_v1_1, v2@sel_1 . v1@sel_2 .@sel_1), merge_join(t@qb_v1_1) */ * from v2;",
"Plan": [
"HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#24)]",
"├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#24",
"│ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#23)]",
"│ ├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#23",
"│ │ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#22)]",
"│ │ ├─HashAgg(Build) 7992.00 root group by:test.t2.a, funcs:count(1)->Column#22",
"│ │ └─HashJoin 12487.50 root inner join, equal:[eq(test.t1.b, test.t2.b)]",
"│ │ ├─TableReader(Build) 9990.00 root data:Selection",
"│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))",
"│ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
"│ │ │ └─TableReader(Probe) 9990.00 root data:Selection",
"│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))",
"│ │ │ ─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
"│ │ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]",
"│ │ ├─TableReader(Build) 9990.00 root data:Selection",
"│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))",
"│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
"│ │ └─TableReader(Probe) 9980.01 root data:Selection",
"│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))",
"│ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo",
"│ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]",
"│ ├─TableReader(Build) 9990.00 root data:Selection",
"│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))",
"│ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
"│ └─TableReader(Probe) 9980.01 root data:Selection",
"│ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))",
"│ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo",
"│ └─HashJoin 12475.01 root inner join, equal:[eq(test.t1.b, test.t.b)]",
"│ ├─MergeJoin(Build) 9980.01 root inner join, left key:test.t.a, right key:Column#23",
"│ │ ├─Sort(Build) 7984.01 root Column#23",
"│ │ │ └─StreamAgg 7984.01 root group by:test.t.a, funcs:count(1)->Column#23",
"│ │ └─Sort 12475.01 root test.t.a",
"│ │ │ └─MergeJoin 12475.01 root inner join, left key:test.t1.b, right key:test.t.b",
"│ │ │ ├─Sort(Build) 9980.01 root test.t.b",
"│ │ └─HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#22)]",
"│ │ │ │ ├─HashAgg(Build) 7992.00 root group by:test.t2.a, funcs:count(1)->Column#22",
"│ │ │ └─HashJoin 12487.50 root inner join, equal:[eq(test.t1.b, test.t2.b)]",
"│ │ ─TableReader(Build) 9990.00 root data:Selection",
"│ │ │ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))",
"│ │ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
"│ │ │ └─TableReader(Probe) 9990.00 root data:Selection",
"│ ││ └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))",
"│ │ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
"│ │ │ └─TableReader(Probe) 9980.01 root data:Selection",
"│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))",
"│ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo",
"│ │ │ └─Sort(Probe) 9990.00 root test.t1.b",
"│ └─TableReader 9990.00 root data:Selection",
"│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))",
"│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
"│ └─Sort(Probe) 9980.01 root test.t.a",
"│ └─TableReader 9980.01 root data:Selection",
"│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))",
"│ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo",
"│ └─TableReader(Probe) 9990.00 root data:Selection",
"│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))",
"│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
"└─TableReader(Probe) 9990.00 root data:Selection",
" └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))",
" └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
@ -4892,7 +4899,9 @@
" └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))",
" └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
],
"Warn": null
"Warn": [
"The qb_name hint qb_v1_2 is unused, please check whether the table list in the qb_name hint qb_v1_2 is correct"
]
},
{
"SQL": "explain format = 'brief' select /*+ qb_name(qb_v1_2, v2@sel_1 . v@sel_1 .@sel_2), merge_join(t1@qb_v1_2) */ * from v2;",
@ -4932,7 +4941,9 @@
" └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))",
" └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
],
"Warn": null
"Warn": [
"The qb_name hint qb_v1_2 is unused, please check whether the table list in the qb_name hint qb_v1_2 is correct"
]
},
{
"SQL": "explain format = 'brief' select /*+ qb_name(qb_v2_2, vv@sel_1 .@sel_2), merge_join(t1@qb_v2_2) */ * from v2 vv;",
@ -5014,7 +5025,9 @@
" └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))",
" └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
],
"Warn": null
"Warn": [
"The qb_name hint qb_v2_2 is unused, please check whether the table list in the qb_name hint qb_v2_2 is correct"
]
},
{
"SQL": "explain format = 'brief' select * from (select /*+ qb_name(qb_v_2, v@sel_1 .@sel_2), merge_join(t1@qb_v_2) */ * from v) t;",
@ -5037,36 +5050,34 @@
" └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
],
"Warn": [
"The qb_name hint for view only supports to be defined in the first query block",
"Hint merge_join(`t1`@`qb_v_2`) is ignored due to unknown query block name"
"The qb_name hint qb_v_2 is unused, please check whether the table list in the qb_name hint qb_v_2 is correct"
]
},
{
"SQL": "explain format = 'brief' select * from (select /*+ qb_name(qb_v_2, v@sel_1 .@sel_2), merge_join(t1@qb_v_2), stream_agg(@qb_v_2), qb_name(qb_v_1, v@sel_1 .@sel1), merge_join(t@qb_v_1) */ * from v) t;",
"SQL": "explain format = 'brief' select * from (select /*+ qb_name(qb_v_2, v.@sel_2), merge_join(t1@qb_v_2), stream_agg(@qb_v_2), qb_name(qb_v_1, v@sel_1 .@sel1), merge_join(t@qb_v_1) */ * from v) t;",
"Plan": [
"HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#13)]",
"├─HashAgg(Build) 7984.01 root group by:test.t2.a, funcs:count(1)->Column#13",
"│ └─HashJoin 15593.77 root inner join, equal:[eq(test.t2.a, test.t3.a)]",
"│ ├─TableReader(Build) 9990.00 root data:Selection",
"│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))",
"│ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo",
"│ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t2.b, test.t1.b)]",
"├─StreamAgg(Build) 7984.01 root group by:test.t2.a, funcs:count(1)->Column#13",
"│ └─Sort 15593.77 root test.t2.a",
"│ └─HashJoin 15593.77 root inner join, equal:[eq(test.t3.a, test.t2.a)]",
"│ ├─TableReader(Build) 9990.00 root data:Selection",
"│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))",
"│ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
"│ └─TableReader(Probe) 9980.01 root data:Selection",
"│ ─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))",
"│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
"│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))",
"│ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo",
"│ └─MergeJoin(Probe) 12475.01 root inner join, left key:test.t1.b, right key:test.t2.b",
"│ ─Sort(Build) 9980.01 root test.t2.b",
"│ └─TableReader 9980.01 root data:Selection",
"│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))",
"│ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
"│ └─Sort(Probe) 9990.00 root test.t1.b",
"│ └─TableReader 9990.00 root data:Selection",
"│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))",
"│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
"└─TableReader(Probe) 9990.00 root data:Selection",
" └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))",
" └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
],
"Warn": [
"The qb_name hint for view only supports to be defined in the first query block",
"The qb_name hint for view only supports to be defined in the first query block",
"Hint merge_join(`t1`@`qb_v_2`) is ignored due to unknown query block name",
"Hint stream_agg(@`qb_v_2`) is ignored due to unknown query block name",
"Hint merge_join(`t`@`qb_v_1`) is ignored due to unknown query block name"
"The qb_name hint qb_v_1 is unused, please check whether the table list in the qb_name hint qb_v_1 is correct"
]
},
{
@ -5099,28 +5110,30 @@
" └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
],
"Warn": [
"The qb_name hint for view only supports to be defined in the first query block",
"Hint merge_join(`t1`@`qb_v_2`) is ignored due to unknown query block name"
"The qb_name hint qb_v_2 is unused, please check whether the table list in the qb_name hint qb_v_2 is correct"
]
},
{
"SQL": "explain format = 'brief' select * from (select /*+ qb_name(qb_v_2, v1@sel_1 . v@sel_2 .@sel_2), merge_join(t1@qb_v_2), stream_agg(@qb_v_2), qb_name(qb_v_1, v1@sel_1 . v@sel_2 .@sel_1), merge_join(t@qb_v_1) */ * from v1) t;",
"SQL": "explain format = 'brief' select * from (select /*+ qb_name(qb_v_2, v1.v@sel_2 .@sel_2), merge_join(t1@qb_v_2), stream_agg(@qb_v_2), qb_name(qb_v_1, v1@sel_1 . v@sel_2 .@sel_1), merge_join(t@qb_v_1) */ * from v1) t;",
"Plan": [
"HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#20)]",
"├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#20",
"│ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#19)]",
"│ ├─HashAgg(Build) 7984.01 root group by:test.t2.a, funcs:count(1)->Column#19",
"│ │ └─HashJoin 15593.77 root inner join, equal:[eq(test.t2.a, test.t3.a)]",
"│ │ ├─TableReader(Build) 9990.00 root data:Selection",
"│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))",
"│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo",
"│ │ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t2.b, test.t1.b)]",
"│ ├─StreamAgg(Build) 7984.01 root group by:test.t2.a, funcs:count(1)->Column#19",
"│ │ └─Sort 15593.77 root test.t2.a",
"│ │ └─HashJoin 15593.77 root inner join, equal:[eq(test.t3.a, test.t2.a)]",
"│ │ ├─TableReader(Build) 9990.00 root data:Selection",
"│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))",
"│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
"│ │ └─TableReader(Probe) 9980.01 root data:Selection",
"│ │ ─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))",
"│ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
"│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))",
"│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo",
"│ │ └─MergeJoin(Probe) 12475.01 root inner join, left key:test.t1.b, right key:test.t2.b",
"│ │ ─Sort(Build) 9980.01 root test.t2.b",
"│ │ └─TableReader 9980.01 root data:Selection",
"│ │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))",
"│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
"│ │ └─Sort(Probe) 9990.00 root test.t1.b",
"│ │ └─TableReader 9990.00 root data:Selection",
"│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))",
"│ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
"│ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]",
"│ ├─TableReader(Build) 9990.00 root data:Selection",
"│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))",
@ -5133,81 +5146,80 @@
" └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
],
"Warn": [
"The qb_name hint for view only supports to be defined in the first query block",
"The qb_name hint for view only supports to be defined in the first query block",
"Hint merge_join(`t1`@`qb_v_2`) is ignored due to unknown query block name",
"Hint stream_agg(@`qb_v_2`) is ignored due to unknown query block name",
"Hint merge_join(`t`@`qb_v_1`) is ignored due to unknown query block name"
"The qb_name hint qb_v_1 is unused, please check whether the table list in the qb_name hint qb_v_1 is correct"
]
},
{
"SQL": "explain format = 'brief' select /*+ qb_name(qb_v_2, v@sel_1 .@sel_2) */ * from (select /*+ merge_join(t1@qb_v_2) */ * from v) t;",
"SQL": "explain format = 'brief' select /*+ qb_name(qb_v_2, v@sel_2 .@sel_2) */ * from (select /*+ merge_join(t1@qb_v_2) */ * from v) t;",
"Plan": [
"HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#13)]",
"├─HashAgg(Build) 7984.01 root group by:test.t2.a, funcs:count(1)->Column#13",
"│ └─HashJoin 15593.77 root inner join, equal:[eq(test.t2.a, test.t3.a)]",
"│ └─HashJoin 15593.77 root inner join, equal:[eq(test.t3.a, test.t2.a)]",
"│ ├─TableReader(Build) 9990.00 root data:Selection",
"│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))",
"│ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo",
"│ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t2.b, test.t1.b)]",
"│ ├─TableReader(Build) 9990.00 root data:Selection",
"│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))",
"│ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
"│ └─TableReader(Probe) 9980.01 root data:Selection",
"│ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))",
"│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
"│ └─MergeJoin(Probe) 12475.01 root inner join, left key:test.t1.b, right key:test.t2.b",
"│ ├─Sort(Build) 9980.01 root test.t2.b",
"│ │ └─TableReader 9980.01 root data:Selection",
"│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))",
"│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
"│ └─Sort(Probe) 9990.00 root test.t1.b",
"│ └─TableReader 9990.00 root data:Selection",
"│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))",
"│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
"└─TableReader(Probe) 9990.00 root data:Selection",
" └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))",
" └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
],
"Warn": [
"Hint merge_join(`t1`@`qb_v_2`) is ignored due to unknown query block name"
]
"Warn": null
},
{
"SQL": "explain format = 'brief' select /*+ qb_name(qb_v_2, v@sel_1 .@sel_2), qb_name(qb_v_1, v@sel_1 .@sel1) */ * from (select /*+ merge_join(t1@qb_v_2), stream_agg(@qb_v_2), merge_join(t@qb_v_1) */ * from v) t;",
"SQL": "explain format = 'brief' select /*+ qb_name(qb_v_2, v@sel_2 .@sel_2), qb_name(qb_v_1, v@sel_2 .@sel1) */ * from (select /*+ merge_join(t1@qb_v_2), stream_agg(@qb_v_2), merge_join(t@qb_v_1) */ * from v) t;",
"Plan": [
"HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#13)]",
"├─HashAgg(Build) 7984.01 root group by:test.t2.a, funcs:count(1)->Column#13",
"│ └─HashJoin 15593.77 root inner join, equal:[eq(test.t2.a, test.t3.a)]",
"│ ├─TableReader(Build) 9990.00 root data:Selection",
"│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))",
"│ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo",
"│ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t2.b, test.t1.b)]",
"├─StreamAgg(Build) 7984.01 root group by:test.t2.a, funcs:count(1)->Column#13",
"│ └─Sort 15593.77 root test.t2.a",
"│ └─HashJoin 15593.77 root inner join, equal:[eq(test.t3.a, test.t2.a)]",
"│ ├─TableReader(Build) 9990.00 root data:Selection",
"│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))",
"│ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
"│ └─TableReader(Probe) 9980.01 root data:Selection",
"│ ─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))",
"│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
"│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))",
"│ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo",
"│ └─MergeJoin(Probe) 12475.01 root inner join, left key:test.t1.b, right key:test.t2.b",
"│ ─Sort(Build) 9980.01 root test.t2.b",
"│ └─TableReader 9980.01 root data:Selection",
"│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))",
"│ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
"│ └─Sort(Probe) 9990.00 root test.t1.b",
"│ └─TableReader 9990.00 root data:Selection",
"│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))",
"│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
"└─TableReader(Probe) 9990.00 root data:Selection",
" └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))",
" └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
],
"Warn": [
"Hint merge_join(`t1`@`qb_v_2`) is ignored due to unknown query block name",
"Hint stream_agg(@`qb_v_2`) is ignored due to unknown query block name",
"Hint merge_join(`t`@`qb_v_1`) is ignored due to unknown query block name"
"The qb_name hint qb_v_1 is unused, please check whether the table list in the qb_name hint qb_v_1 is correct"
]
},
{
"SQL": "explain format = 'brief' select /*+ qb_name(qb_v_2, v1@sel_1 . v@sel_2 .@sel_2) */ * from (select /*+ merge_join(t1@qb_v_2) */ * from v1) t;",
"SQL": "explain format = 'brief' select /*+ qb_name(qb_v_2, v1@sel_2 . v@sel_2 .@sel_2) */ * from (select /*+ merge_join(t1@qb_v_2) */ * from v1) t;",
"Plan": [
"HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#20)]",
"├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#20",
"│ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#19)]",
"│ ├─HashAgg(Build) 7984.01 root group by:test.t2.a, funcs:count(1)->Column#19",
"│ │ └─HashJoin 15593.77 root inner join, equal:[eq(test.t2.a, test.t3.a)]",
"│ │ └─HashJoin 15593.77 root inner join, equal:[eq(test.t3.a, test.t2.a)]",
"│ │ ├─TableReader(Build) 9990.00 root data:Selection",
"│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))",
"│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo",
"│ │ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t2.b, test.t1.b)]",
"│ │ ├─TableReader(Build) 9990.00 root data:Selection",
"│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))",
"│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
"│ │ └─TableReader(Probe) 9980.01 root data:Selection",
"│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))",
"│ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
"│ │ └─MergeJoin(Probe) 12475.01 root inner join, left key:test.t1.b, right key:test.t2.b",
"│ │ ├─Sort(Build) 9980.01 root test.t2.b",
"│ │ │ └─TableReader 9980.01 root data:Selection",
"│ │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))",
"│ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
"│ │ └─Sort(Probe) 9990.00 root test.t1.b",
"│ │ └─TableReader 9990.00 root data:Selection",
"│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))",
"│ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
"│ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]",
"│ ├─TableReader(Build) 9990.00 root data:Selection",
"│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))",
@ -5219,72 +5231,73 @@
" └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))",
" └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
],
"Warn": [
"Hint merge_join(`t1`@`qb_v_2`) is ignored due to unknown query block name"
]
"Warn": null
},
{
"SQL": "explain format = 'brief' select /*+ qb_name(qb_v_2, v1@sel_1 . v@sel_2 .@sel_2), qb_name(qb_v_1, v1@sel_1 . v@sel_2 .@sel_1) */ * from (select /*+ merge_join(t1@qb_v_2), stream_agg(@qb_v_2), merge_join(t@qb_v_1) */ * from v1) t;",
"SQL": "explain format = 'brief' select /*+ qb_name(qb_v_2, v1@sel_2 . v@sel_2 .@sel_2), qb_name(qb_v_1, v1@sel_2 . v@sel_2 .@sel_1) */ * from (select /*+ merge_join(t1@qb_v_2), stream_agg(@qb_v_2), merge_join(t@qb_v_1) */ * from v1) t;",
"Plan": [
"HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#20)]",
"├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#20",
"│ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#19)]",
"│ ├─HashAgg(Build) 7984.01 root group by:test.t2.a, funcs:count(1)->Column#19",
"│ │ └─HashJoin 15593.77 root inner join, equal:[eq(test.t2.a, test.t3.a)]",
"│ │ ├─TableReader(Build) 9990.00 root data:Selection",
"│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))",
"│ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo",
"│ │ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t2.b, test.t1.b)]",
"│ │ ├─TableReader(Build) 9990.00 root data:Selection",
"│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))",
"│ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
"│ │ └─TableReader(Probe) 9980.01 root data:Selection",
"│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))",
"│ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
"│ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]",
"│ ├─TableReader(Build) 9990.00 root data:Selection",
"│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))",
"│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
"│ └─TableReader(Probe) 9980.01 root data:Selection",
"│ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))",
"│ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo",
"│ └─HashJoin 12475.01 root inner join, equal:[eq(test.t1.b, test.t.b)]",
"│ ├─MergeJoin(Build) 9980.01 root inner join, left key:test.t.a, right key:Column#19",
"│ │ ├─Sort(Build) 7984.01 root Column#19",
"│ │ │ └─StreamAgg 7984.01 root group by:test.t2.a, funcs:count(1)->Column#19",
"│ │ └─Sort 15593.77 root test.t2.a",
"│ │ └─HashJoin 15593.77 root inner join, equal:[eq(test.t3.a, test.t2.a)]",
"│ │ │ ├─TableReader(Build) 9990.00 root data:Selection",
"│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))",
"│ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo",
"│ │ └─MergeJoin(Probe) 12475.01 root inner join, left key:test.t1.b, right key:test.t2.b",
"│ │ ├─Sort(Build) 9980.01 root test.t2.b",
"│ │ │ └─TableReader 9980.01 root data:Selection",
"│ │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))",
"│ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
"│ │ │ └─Sort(Probe) 9990.00 root test.t1.b",
"│ │ │ └─TableReader 9990.00 root data:Selection",
"│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))",
"│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
"│ └─Sort(Probe) 9980.01 root test.t.a",
"│ └─TableReader 9980.01 root data:Selection",
"│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))",
"│ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo",
"│ └─TableReader(Probe) 9990.00 root data:Selection",
"│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))",
"│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
"└─TableReader(Probe) 9990.00 root data:Selection",
" └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))",
" └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
],
"Warn": [
"Hint merge_join(`t1`@`qb_v_2`) is ignored due to unknown query block name",
"Hint stream_agg(@`qb_v_2`) is ignored due to unknown query block name",
"Hint merge_join(`t`@`qb_v_1`) is ignored due to unknown query block name"
]
"Warn": null
},
{
"SQL": "explain format = 'brief' select /*+ qb_name(qb_v1_2, v2@sel_1 . v1@sel_1 .@sel_2), qb_name(qb_v1_1, v2@sel_1 . v1@sel_1 .@sel_1), merge_join(t1@qb_v1_2, t@qb_v1_1) */ * from v2;",
"SQL": "explain format = 'brief' select /*+ qb_name(qb_v1_2, v2. v1@sel_2 .@sel_2), qb_name(qb_v1_1, v2@sel_1 . v1@sel_2 .@sel_1), merge_join(t1@qb_v1_2, t@qb_v1_1), merge_join(t1@qb_v1_2) */ * from v2;",
"Plan": [
"HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#27)]",
"├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#27",
"│ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#26)]",
"│ ├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#26",
"│ │ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#25)]",
"│ │ ├─HashAgg(Build) 7984.01 root group by:test.t2.a, funcs:count(1)->Column#25",
"│ │ │ └─HashJoin 15593.77 root inner join, equal:[eq(test.t2.a, test.t3.a)]",
"│ │ │ ├─TableReader(Build) 9990.00 root data:Selection",
"│ │ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))",
"│ │ │ │ ─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo",
"│ │ │ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t2.b, test.t1.b)]",
"│ │ │ ├─TableReader(Build) 9990.00 root data:Selection",
"│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))",
"│ │ │ ─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
"│ │ │ └─TableReader(Probe) 9980.01 root data:Selection",
"│ │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))",
"│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
"│ │ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]",
"│ │ ├─TableReader(Build) 9990.00 root data:Selection",
"│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))",
"│ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
"│ │ └─TableReader(Probe) 9980.01 root data:Selection",
"│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))",
"│ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo",
"│ │ └─MergeJoin 12475.01 root inner join, left key:test.t1.b, right key:test.t.b",
"│ │ ├─Sort(Build) 9980.01 root test.t.b",
"│ │ │ └─HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#25)]",
"│ │ │ ├─HashAgg(Build) 7984.01 root group by:test.t2.a, funcs:count(1)->Column#25",
"│ │ │ │ └─HashJoin 15593.77 root inner join, equal:[eq(test.t2.a, test.t3.a)]",
"│ │ │ │ ─TableReader(Build) 9990.00 root data:Selection",
"│ │ │ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))",
"│ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo",
"│ │ │ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t2.b, test.t1.b)]",
"│ │ │ │ ─TableReader(Build) 9990.00 root data:Selection",
"│ │ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))",
"│ │ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
"│ │ │ └─TableReader(Probe) 9980.01 root data:Selection",
"│ │ │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))",
"│ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
"│ │ └─TableReader(Probe) 9980.01 root data:Selection",
"│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))",
"│ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo",
"│ │ └─Sort(Probe) 9990.00 root test.t1.b",
"│ │ └─TableReader 9990.00 root data:Selection",
"│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))",
"│ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
"│ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]",
"│ ├─TableReader(Build) 9990.00 root data:Selection",
"│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))",
@ -5640,6 +5653,51 @@
"[planner:1815]Join hints are conflict, you can only specify one type of join",
"[planner:1815]Optimizer aggregation hints are conflicted"
]
},
{
"SQL": "explain with d1 as (\n select a from (\n select a from (\n select /*+ qb_name(qb, v4) use_index(t4@qb, idx_a) */ a from v4 where a < 10\n ) as t0 where a < 9\n ) as t1 where a < 8\n), d2 as (select /*+ qb_name(qb2, v4) use_index(t4@qb2, idx_b) */ a from v4 where b < 10)\n\nselect * from (select * from d1) as t0 join (select * from d2) as t1;",
"Plan": [
"HashJoin_41 6944.44 root CARTESIAN inner join",
"├─IndexLookUp_50(Build) 83.33 root ",
"│ ├─IndexRangeScan_47(Build) 250.00 cop[tikv] table:t4, index:idx_b(b) range:(3,10), keep order:false, stats:pseudo",
"│ └─Selection_49(Probe) 83.33 cop[tikv] gt(test.t4.a, 2)",
"│ └─TableRowIDScan_48 250.00 cop[tikv] table:t4 keep order:false, stats:pseudo",
"└─IndexLookUp_46(Probe) 83.33 root ",
" ├─IndexRangeScan_43(Build) 250.00 cop[tikv] table:t4, index:idx_a(a) range:(2,8), keep order:false, stats:pseudo",
" └─Selection_45(Probe) 83.33 cop[tikv] gt(test.t4.b, 3)",
" └─TableRowIDScan_44 250.00 cop[tikv] table:t4 keep order:false, stats:pseudo"
],
"Warn": null
},
{
"SQL": "explain with d1 as (\n select a from (\n select a from (\n select a from v4 where a < 10\n ) as t0 where a < 9\n ) as t1 where a < 8\n), d2 as (select a from v4 where b < 10)\n\nselect /*+ qb_name(qb, v4@sel_4) use_index(t4@qb, idx_a) qb_name(qb2, v4@sel_5) use_index(t4@qb, idx_b) */ * from (select * from d1) as t0 join (select * from d2) as t1;",
"Plan": [
"HashJoin_41 6944.44 root CARTESIAN inner join",
"├─TableReader_53(Build) 83.33 root data:Selection_52",
"│ └─Selection_52 83.33 cop[tikv] gt(test.t4.a, 2), gt(test.t4.b, 3), lt(test.t4.b, 10)",
"│ └─TableFullScan_51 10000.00 cop[tikv] table:t4 keep order:false, stats:pseudo",
"└─IndexLookUp_46(Probe) 83.33 root ",
" ├─IndexRangeScan_43(Build) 250.00 cop[tikv] table:t4, index:idx_a(a) range:(2,8), keep order:false, stats:pseudo",
" └─Selection_45(Probe) 83.33 cop[tikv] gt(test.t4.b, 3)",
" └─TableRowIDScan_44 250.00 cop[tikv] table:t4 keep order:false, stats:pseudo"
],
"Warn": null
},
{
"SQL": "explain with d1 as (\n select a from (\n select a from (\n select /*+ qb_name(qb, v5) use_index(t4@qb, idx_a) */ a from v4 where a < 10\n ) as t0 where a < 9\n ) as t1 where a < 8\n), d2 as (select /*+ qb_name(qb2, v4) use_index(t4@qb2, idx_b) */ a from v4 where b < 10)\n\nselect * from (select * from d1) as t0 join (select * from d2) as t1;",
"Plan": [
"HashJoin_41 6944.44 root CARTESIAN inner join",
"├─IndexLookUp_57(Build) 83.33 root ",
"│ ├─IndexRangeScan_54(Build) 250.00 cop[tikv] table:t4, index:idx_b(b) range:(3,10), keep order:false, stats:pseudo",
"│ └─Selection_56(Probe) 83.33 cop[tikv] gt(test.t4.a, 2)",
"│ └─TableRowIDScan_55 250.00 cop[tikv] table:t4 keep order:false, stats:pseudo",
"└─TableReader_45(Probe) 83.33 root data:Selection_44",
" └─Selection_44 83.33 cop[tikv] gt(test.t4.a, 2), gt(test.t4.b, 3), lt(test.t4.a, 10), lt(test.t4.a, 8), lt(test.t4.a, 9)",
" └─TableFullScan_43 10000.00 cop[tikv] table:t4 keep order:false, stats:pseudo"
],
"Warn": [
"The qb_name hint qb is unused, please check whether the table list in the qb_name hint qb is correct"
]
}
]
},

View File

@ -356,6 +356,7 @@ func optimize(ctx context.Context, sctx sessionctx.Context, node ast.Node, is in
// build logical plan
hintProcessor := &hint.BlockHintProcessor{Ctx: sctx}
node.Accept(hintProcessor)
defer hintProcessor.HandleUnusedViewHints()
builder := planBuilderPool.Get().(*core.PlanBuilder)
defer planBuilderPool.Put(builder.ResetForReuse())
builder.Init(sctx, is, hintProcessor)

View File

@ -325,8 +325,9 @@ type BlockHintProcessor struct {
QbHints map[int][]*ast.TableOptimizerHint // Group all hints at same query block.
// Used for the view's hint
QbNameMap4View map[string][]ast.HintTable // Map from view's query block name to view's table list.
QbHints4View map[string][]*ast.TableOptimizerHint // Group all hints at same query block for view hints.
QbNameMap4View map[string][]ast.HintTable // Map from view's query block name to view's table list.
QbHints4View map[string][]*ast.TableOptimizerHint // Group all hints at same query block for view hints.
QbNameUsed4View map[string]struct{} // Store all the qb_name hints which are used for view
Ctx sessionctx.Context
selectStmtOffset int
@ -346,15 +347,14 @@ func (p *BlockHintProcessor) Enter(in ast.Node) (ast.Node, bool) {
p.checkQueryBlockHints(node.TableHints, 0)
case *ast.SelectStmt:
p.selectStmtOffset++
// Only support view hints which appear in the outer select part
if p.selectStmtOffset == 1 {
// Handle the view hints and update the left hint.
node.TableHints = p.handleViewHints(node.TableHints)
}
node.QueryBlockOffset = p.selectStmtOffset
// Handle the view hints and update the left hint.
node.TableHints = p.handleViewHints(node.TableHints, node.QueryBlockOffset)
p.checkQueryBlockHints(node.TableHints, node.QueryBlockOffset)
case *ast.ExplainStmt:
return in, true
case *ast.CreateBindingStmt:
return in, true
}
return in, false
}
@ -373,12 +373,6 @@ func (p *BlockHintProcessor) checkQueryBlockHints(hints []*ast.TableOptimizerHin
if hint.HintName.L != hintQBName {
continue
}
if offset > 1 && len(hint.Tables) > 0 {
if p.Ctx != nil {
p.Ctx.GetSessionVars().StmtCtx.AppendWarning(fmt.Errorf("The qb_name hint for view only supports to be defined in the first query block"))
}
continue
}
if qbName != "" {
if p.Ctx != nil {
p.Ctx.GetSessionVars().StmtCtx.AppendWarning(fmt.Errorf("There are more than two query names in same query block, using the first one %s", qbName))
@ -402,7 +396,7 @@ func (p *BlockHintProcessor) checkQueryBlockHints(hints []*ast.TableOptimizerHin
}
}
func (p *BlockHintProcessor) handleViewHints(hints []*ast.TableOptimizerHint) (leftHints []*ast.TableOptimizerHint) {
func (p *BlockHintProcessor) handleViewHints(hints []*ast.TableOptimizerHint, offset int) (leftHints []*ast.TableOptimizerHint) {
if len(hints) == 0 {
return
}
@ -416,6 +410,7 @@ func (p *BlockHintProcessor) handleViewHints(hints []*ast.TableOptimizerHint) (l
usedHints[i] = true
if p.QbNameMap4View == nil {
p.QbNameMap4View = make(map[string][]ast.HintTable)
p.QbNameUsed4View = make(map[string]struct{})
}
qbName := hint.QBName.L
if qbName == "" {
@ -426,6 +421,14 @@ func (p *BlockHintProcessor) handleViewHints(hints []*ast.TableOptimizerHint) (l
p.Ctx.GetSessionVars().StmtCtx.AppendWarning(fmt.Errorf("Duplicate query block name %s for view's query block hint, only the first one is effective", qbName))
}
} else {
if offset != 1 {
// If there are some qb_name hints for view are not defined in the first query block,
// we should add the query block number where it is located to the first table in the view's qb_name hint table list.
qbNum := hint.Tables[0].QBName.L
if qbNum == "" {
hint.Tables[0].QBName = model.NewCIStr(fmt.Sprintf("%s%d", defaultSelectBlockPrefix, offset))
}
}
p.QbNameMap4View[qbName] = hint.Tables
}
}
@ -475,6 +478,18 @@ func (p *BlockHintProcessor) handleViewHints(hints []*ast.TableOptimizerHint) (l
return
}
// HandleUnusedViewHints handle the unused view hints.
func (p *BlockHintProcessor) HandleUnusedViewHints() {
if p.QbNameMap4View != nil {
for qbName := range p.QbNameMap4View {
_, ok := p.QbNameUsed4View[qbName]
if !ok && p.Ctx != nil {
p.Ctx.GetSessionVars().StmtCtx.AppendWarning(fmt.Errorf("The qb_name hint %s is unused, please check whether the table list in the qb_name hint %s is correct", qbName, qbName))
}
}
}
}
const (
defaultUpdateBlockName = "upd_1"
defaultDeleteBlockName = "del_1"