From 679d2e559cab8d866d8607518435cd6944c669bb Mon Sep 17 00:00:00 2001 From: Zhang Jian Date: Tue, 13 Nov 2018 11:55:30 +0800 Subject: [PATCH] planner/core: make TIDB_INLJ to specify the inner table (#8243) --- executor/index_lookup_join_test.go | 2 +- executor/join_test.go | 22 +++++++++++----------- planner/core/exhaust_physical_plans.go | 4 ++-- planner/core/logical_plan_builder.go | 11 +++++------ planner/core/logical_plans.go | 4 ++-- planner/core/physical_plan_test.go | 16 ++++++++-------- 6 files changed, 29 insertions(+), 30 deletions(-) diff --git a/executor/index_lookup_join_test.go b/executor/index_lookup_join_test.go index 319e6e60e56c8..3da1ede553a4f 100644 --- a/executor/index_lookup_join_test.go +++ b/executor/index_lookup_join_test.go @@ -29,7 +29,7 @@ func (s *testSuite) TestIndexLookupJoinHang(c *C) { tk.Se.GetSessionVars().IndexJoinBatchSize = 1 tk.Se.GetSessionVars().IndexLookupJoinConcurrency = 1 - rs, err := tk.Exec("select /*+ TIDB_INLJ(o, i)*/ * from idxJoinOuter o left join idxJoinInner i on o.a = i.a where o.a in (1, 2) and (i.a - 3) > 0") + rs, err := tk.Exec("select /*+ TIDB_INLJ(i)*/ * from idxJoinOuter o left join idxJoinInner i on o.a = i.a where o.a in (1, 2) and (i.a - 3) > 0") c.Assert(err, IsNil) chk := rs.NewChunk() for i := 0; i < 5; i++ { diff --git a/executor/join_test.go b/executor/join_test.go index 9310c7677e3c3..c567dc241327b 100644 --- a/executor/join_test.go +++ b/executor/join_test.go @@ -145,11 +145,11 @@ func (s *testSuite) TestJoin(c *C) { // The physical plans of the two sql are tested at physical_plan_test.go tk.MustQuery("select /*+ TIDB_INLJ(t, t1) */ * from t join t1 on t.a=t1.a").Check(testkit.Rows("1 1 1 2", "1 1 1 3", "1 1 1 4", "3 3 3 4")) - tk.MustQuery("select /*+ TIDB_INLJ(t1) */ * from t1 join t on t.a=t1.a and t.a < t1.b").Check(testkit.Rows("1 2 1 1", "1 3 1 1", "1 4 1 1", "3 4 3 3")) + tk.MustQuery("select /*+ TIDB_INLJ(t) */ * from t1 join t on t.a=t1.a and t.a < t1.b").Check(testkit.Rows("1 2 1 1", "1 3 1 1", "1 4 1 1", "3 4 3 3")) // Test single index reader. tk.MustQuery("select /*+ TIDB_INLJ(t, t1) */ t1.b from t1 join t on t.b=t1.b").Check(testkit.Rows("2", "3")) - tk.MustQuery("select /*+ TIDB_INLJ(t, t1) */ * from t right outer join t1 on t.a=t1.a").Check(testkit.Rows("1 1 1 2", "1 1 1 3", "1 1 1 4", "3 3 3 4", " 4 5")) - tk.MustQuery("select /*+ TIDB_INLJ(t, t1) */ avg(t.b) from t right outer join t1 on t.a=t1.a").Check(testkit.Rows("1.5000")) + tk.MustQuery("select /*+ TIDB_INLJ(t1) */ * from t right outer join t1 on t.a=t1.a").Check(testkit.Rows("1 1 1 2", "1 1 1 3", "1 1 1 4", "3 3 3 4", " 4 5")) + tk.MustQuery("select /*+ TIDB_INLJ(t) */ avg(t.b) from t right outer join t1 on t.a=t1.a").Check(testkit.Rows("1.5000")) // Test that two conflict hints will return error. _, err = tk.Exec("select /*+ TIDB_INLJ(t) TIDB_SMJ(t) */ * from t join t1 on t.a=t1.a") @@ -169,8 +169,8 @@ func (s *testSuite) TestJoin(c *C) { tk.MustExec("create table t1(a int, b int)") tk.MustExec("insert into t values(1, 3), (2, 2), (3, 1)") tk.MustExec("insert into t1 values(0, 0), (1, 2), (1, 3), (3, 4)") - tk.MustQuery("select /*+ TIDB_INLJ(t) */ * from t join t1 on t.a=t1.a order by t.b").Check(testkit.Rows("3 1 3 4", "1 3 1 2", "1 3 1 3")) - tk.MustQuery("select /*+ TIDB_INLJ(t1) */ t.a, t.b from t join t1 on t.a=t1.a where t1.b = 4 limit 1").Check(testkit.Rows("3 1")) + tk.MustQuery("select /*+ TIDB_INLJ(t1) */ * from t join t1 on t.a=t1.a order by t.b").Check(testkit.Rows("3 1 3 4", "1 3 1 2", "1 3 1 3")) + tk.MustQuery("select /*+ TIDB_INLJ(t) */ t.a, t.b from t join t1 on t.a=t1.a where t1.b = 4 limit 1").Check(testkit.Rows("3 1")) tk.MustQuery("select /*+ TIDB_INLJ(t, t1) */ * from t right join t1 on t.a=t1.a order by t.b").Check(testkit.Rows(" 0 0", "3 1 3 4", "1 3 1 2", "1 3 1 3")) // join reorder will disorganize the resulting schema @@ -187,7 +187,7 @@ func (s *testSuite) TestJoin(c *C) { tk.MustExec("create table t1(a int)") tk.MustExec("insert into t values(1,2), (5,3), (6,4)") tk.MustExec("insert into t1 values(1), (2), (3)") - tk.MustQuery("select /*+ TIDB_INLJ(t1) */ t1.a from t1, t where t.a = 5 and t.b = t1.a").Check(testkit.Rows("3")) + tk.MustQuery("select /*+ TIDB_INLJ(t) */ t1.a from t1, t where t.a = 5 and t.b = t1.a").Check(testkit.Rows("3")) // test issue#4997 tk.MustExec("drop table if exists t1, t2") @@ -326,7 +326,7 @@ func (s *testSuite) TestJoinCast(c *C) { tk.MustExec("create index k1 on t1(c1)") tk.MustExec("insert into t values(0), (2)") tk.MustExec("insert into t1 values(0), (9)") - result = tk.MustQuery("select /*+ TIDB_INLJ(t) */ * from t left join t1 on t1.c1 = t.c1") + result = tk.MustQuery("select /*+ TIDB_INLJ(t1) */ * from t left join t1 on t1.c1 = t.c1") result.Sort().Check(testkit.Rows("0.0 0.00", "2.0 ")) tk.MustExec("drop table if exists t") @@ -672,7 +672,7 @@ func (s *testSuite) TestSubquery(c *C) { tk.MustExec("CREATE TABLE t1(a int, b int default 0)") tk.MustExec("create index k1 on t1(a)") tk.MustExec("INSERT INTO t1 (a) values(1), (2), (3), (4), (5)") - result = tk.MustQuery("select (select /*+ TIDB_INLJ(x1) */ x2.a from t1 x1, t1 x2 where x1.a = t1.a and x1.a = x2.a) from t1") + result = tk.MustQuery("select (select /*+ TIDB_INLJ(x2) */ x2.a from t1 x1, t1 x2 where x1.a = t1.a and x1.a = x2.a) from t1") result.Check(testkit.Rows("1", "2", "3", "4", "5")) tk.MustExec("drop table if exists t1, t2") @@ -809,7 +809,7 @@ func (s *testSuite) TestIssue5255(c *C) { tk.MustExec("create table t2(a int primary key)") tk.MustExec("insert into t1 values(1, '2017-11-29', 2.2)") tk.MustExec("insert into t2 values(1)") - tk.MustQuery("select /*+ TIDB_INLJ(t2) */ * from t1 join t2 on t1.a=t2.a").Check(testkit.Rows("1 2017-11-29 2.2 1")) + tk.MustQuery("select /*+ TIDB_INLJ(t1) */ * from t1 join t2 on t1.a=t2.a").Check(testkit.Rows("1 2017-11-29 2.2 1")) } func (s *testSuite) TestIssue5278(c *C) { @@ -847,7 +847,7 @@ func (s *testSuite) TestIndexLookupJoin(c *C) { tk.MustExec(`drop table if exists t;`) tk.MustExec(`create table t(a decimal(6,2), index idx(a));`) tk.MustExec(`insert into t values(1.01), (2.02), (NULL);`) - tk.MustQuery(`select /*+ TIDB_INLJ(t1) */ t1.a from t t1 join t t2 on t1.a=t2.a order by t1.a;`).Check(testkit.Rows( + tk.MustQuery(`select /*+ TIDB_INLJ(t2) */ t1.a from t t1 join t t2 on t1.a=t2.a order by t1.a;`).Check(testkit.Rows( `1.01`, `2.02`, )) @@ -856,7 +856,7 @@ func (s *testSuite) TestIndexLookupJoin(c *C) { tk.MustExec(`create table t(a bigint, b bigint, unique key idx1(a, b));`) tk.MustExec(`insert into t values(1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6);`) tk.MustExec(`set @@tidb_max_chunk_size = 2;`) - tk.MustQuery(`select /*+ TIDB_INLJ(t1) */ * from t t1 left join t t2 on t1.a = t2.a and t1.b = t2.b + 4;`).Check(testkit.Rows( + tk.MustQuery(`select /*+ TIDB_INLJ(t2) */ * from t t1 left join t t2 on t1.a = t2.a and t1.b = t2.b + 4;`).Check(testkit.Rows( `1 1 `, `1 2 `, `1 3 `, diff --git a/planner/core/exhaust_physical_plans.go b/planner/core/exhaust_physical_plans.go index 0a8766c0b42ec..67afd825f923b 100644 --- a/planner/core/exhaust_physical_plans.go +++ b/planner/core/exhaust_physical_plans.go @@ -602,8 +602,8 @@ func (p *LogicalJoin) tryToGetIndexJoin(prop *property.PhysicalProperty) ([]Phys return nil, false } plans := make([]PhysicalPlan, 0, 2) - leftOuter := (p.preferJoinType & preferLeftAsIndexOuter) > 0 - rightOuter := (p.preferJoinType & preferRightAsIndexOuter) > 0 + rightOuter := (p.preferJoinType & preferLeftAsIndexInner) > 0 + leftOuter := (p.preferJoinType & preferRightAsIndexInner) > 0 switch p.JoinType { case SemiJoin, AntiSemiJoin, LeftOuterSemiJoin, AntiLeftOuterSemiJoin, LeftOuterJoin: join := p.getIndexJoinByOuterIdx(prop, 0) diff --git a/planner/core/logical_plan_builder.go b/planner/core/logical_plan_builder.go index f35ba0a2e3e5b..d67d4940966d1 100644 --- a/planner/core/logical_plan_builder.go +++ b/planner/core/logical_plan_builder.go @@ -258,15 +258,15 @@ func (p *LogicalJoin) setPreferredJoinType(hintInfo *tableHintInfo) error { p.preferJoinType |= preferHashJoin } if hintInfo.ifPreferINLJ(lhsAlias) { - p.preferJoinType |= preferLeftAsIndexOuter + p.preferJoinType |= preferLeftAsIndexInner } if hintInfo.ifPreferINLJ(rhsAlias) { - p.preferJoinType |= preferRightAsIndexOuter + p.preferJoinType |= preferRightAsIndexInner } // If there're multiple join types and one of them is not index join hint, // then there is a conflict of join types. - if bits.OnesCount(p.preferJoinType) > 1 && (p.preferJoinType^preferRightAsIndexOuter^preferLeftAsIndexOuter) > 0 { + if bits.OnesCount(p.preferJoinType) > 1 && (p.preferJoinType^preferRightAsIndexInner^preferLeftAsIndexInner) > 0 { return errors.New("Join hints are conflict, you can only specify one type of join") } return nil @@ -2031,9 +2031,8 @@ func (b *PlanBuilder) buildSemiJoin(outerPlan, innerPlan LogicalPlan, onConditio if b.TableHints().ifPreferHashJoin(outerAlias, innerAlias) { joinPlan.preferJoinType |= preferHashJoin } - // semi join's outer is always the left side. - if b.TableHints().ifPreferINLJ(outerAlias) { - joinPlan.preferJoinType = preferLeftAsIndexOuter + if b.TableHints().ifPreferINLJ(innerAlias) { + joinPlan.preferJoinType = preferLeftAsIndexInner } // If there're multiple join hints, they're conflict. if bits.OnesCount(joinPlan.preferJoinType) > 1 { diff --git a/planner/core/logical_plans.go b/planner/core/logical_plans.go index cbb1f9b020dd6..aa2cc510b67c9 100644 --- a/planner/core/logical_plans.go +++ b/planner/core/logical_plans.go @@ -85,8 +85,8 @@ func (tp JoinType) String() string { } const ( - preferLeftAsIndexOuter = 1 << iota - preferRightAsIndexOuter + preferLeftAsIndexInner = 1 << iota + preferRightAsIndexInner preferHashJoin preferMergeJoin ) diff --git a/planner/core/physical_plan_test.go b/planner/core/physical_plan_test.go index ef972b38a8456..0a9371674e373 100644 --- a/planner/core/physical_plan_test.go +++ b/planner/core/physical_plan_test.go @@ -373,7 +373,7 @@ func (s *testPlanSuite) TestDAGPlanBuilderJoin(c *C) { }, // Test Index Join + TableScan + Rotate. { - sql: "select /*+ TIDB_INLJ(t2) */ t1.a , t2.a from t t1, t t2 where t1.a = t2.c", + sql: "select /*+ TIDB_INLJ(t1) */ t1.a , t2.a from t t1, t t2 where t1.a = t2.c", best: "IndexJoin{TableReader(Table(t))->TableReader(Table(t))}(t2.c,t1.a)->Projection", }, // Test Index Join + OuterJoin + TableScan. @@ -392,33 +392,33 @@ func (s *testPlanSuite) TestDAGPlanBuilderJoin(c *C) { }, // Test Index Join failed. { - sql: "select /*+ TIDB_INLJ(t1) */ * from t t1 right outer join t t2 on t1.a = t2.b", + sql: "select /*+ TIDB_INLJ(t2) */ * from t t1 right outer join t t2 on t1.a = t2.b", best: "RightHashJoin{TableReader(Table(t))->TableReader(Table(t))}(t1.a,t2.b)", }, // Test Semi Join hint success. { - sql: "select /*+ TIDB_INLJ(t1) */ * from t t1 where t1.a in (select a from t t2)", + sql: "select /*+ TIDB_INLJ(t2) */ * from t t1 where t1.a in (select a from t t2)", best: "IndexJoin{TableReader(Table(t))->TableReader(Table(t))}(t1.a,t2.a)->Projection", }, // Test Semi Join hint fail. { - sql: "select /*+ TIDB_INLJ(t2) */ * from t t1 where t1.a in (select a from t t2)", + sql: "select /*+ TIDB_INLJ(t1) */ * from t t1 where t1.a in (select a from t t2)", best: "IndexJoin{TableReader(Table(t))->TableReader(Table(t))}(t2.a,t1.a)->Projection", }, { - sql: "select /*+ TIDB_INLJ(t1) */ * from t t1 join t t2 where t1.c=t2.c and t1.f=t2.f", + sql: "select /*+ TIDB_INLJ(t2) */ * from t t1 join t t2 where t1.c=t2.c and t1.f=t2.f", best: "IndexJoin{TableReader(Table(t))->IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))}(t1.c,t2.c)", }, { - sql: "select /*+ TIDB_INLJ(t1) */ * from t t1 join t t2 where t1.a = t2.a and t1.f=t2.f", + sql: "select /*+ TIDB_INLJ(t2) */ * from t t1 join t t2 where t1.a = t2.a and t1.f=t2.f", best: "IndexJoin{TableReader(Table(t))->TableReader(Table(t))}(t1.a,t2.a)", }, { - sql: "select /*+ TIDB_INLJ(t1) */ * from t t1 join t t2 where t1.f=t2.f and t1.a=t2.a", + sql: "select /*+ TIDB_INLJ(t2) */ * from t t1 join t t2 where t1.f=t2.f and t1.a=t2.a", best: "IndexJoin{TableReader(Table(t))->TableReader(Table(t))}(t1.a,t2.a)", }, { - sql: "select /*+ TIDB_INLJ(t1) */ * from t t1 join t t2 where t1.a=t2.a and t2.a in (1, 2)", + sql: "select /*+ TIDB_INLJ(t2) */ * from t t1 join t t2 where t1.a=t2.a and t2.a in (1, 2)", best: "IndexJoin{TableReader(Table(t))->TableReader(Table(t)->Sel([in(t2.a, 1, 2)]))}(t1.a,t2.a)", }, }