Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

plan: Choose left table as build table for semi join when left one is smaller for MPPTask #43064

Merged
merged 5 commits into from
Apr 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions planner/core/casetest/physical_plan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -941,6 +941,62 @@ func TestMPPBCJModelOneTiFlash(t *testing.T) {
}
}

func TestMPPRightSemiJoin(t *testing.T) {
store := testkit.CreateMockStore(t, internal.WithMockTiFlash(3))
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t1")
tk.MustExec("create table t1 (a int)")
tk.MustExec("drop table if exists t2")
tk.MustExec("create table t2 (b int)")

tk.MustExec("insert into t1 values (1);")
tk.MustExec("insert into t2 values (1), (2), (3), (4), (5), (6), (7), (8);")

{
tk.MustExec("alter table t1 set tiflash replica 1")
tb := external.GetTableByName(t, tk, "test", "t1")
err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true)
require.NoError(t, err)
}
{
tk.MustExec("alter table t2 set tiflash replica 1")
tb := external.GetTableByName(t, tk, "test", "t2")
err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true)
require.NoError(t, err)
}
tk.MustExec("analyze table t1")
tk.MustExec("analyze table t2")
tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1;")
{
var input []string
var output []struct {
SQL string
Plan []string
Warn []string
}
planSuiteData := GetPlanSuiteData()
planSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
})
if strings.HasPrefix(tt, "set") || strings.HasPrefix(tt, "insert") {
tk.MustExec(tt)
continue
}
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
output[i].Warn = testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
require.Equal(t, output[i].Warn, testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings()))
}
}
}

func TestHintScope(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
Expand Down
7 changes: 7 additions & 0 deletions planner/core/casetest/testdata/plan_suite_in.json
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,13 @@
"explain select * from t t1, t t2 where t1.a=t2.a"
]
},
{
"name": "TestMPPRightSemiJoin",
"cases": [
"set @@session.tidb_allow_mpp=true",
"explain select * from t1 where exists (select * from t2 where t1.a=t2.b)"
]
},
{
"name": "TestIssue37520",
"cases": [
Expand Down
25 changes: 25 additions & 0 deletions planner/core/casetest/testdata/plan_suite_out.json
Original file line number Diff line number Diff line change
Expand Up @@ -1564,6 +1564,31 @@
}
]
},
{
"Name": "TestMPPRightSemiJoin",
"Cases": [
{
"SQL": "set @@session.tidb_allow_mpp=true",
"Plan": null,
"Warn": null
},
{
"SQL": "explain select * from t1 where exists (select * from t2 where t1.a=t2.b)",
"Plan": [
"TableReader_34 0.80 root MppVersion: 1, data:ExchangeSender_33",
"└─ExchangeSender_33 0.80 mpp[tiflash] ExchangeType: PassThrough",
" └─HashJoin_32 0.80 mpp[tiflash] semi join, equal:[eq(test.t1.a, test.t2.b)]",
" ├─ExchangeReceiver_15(Build) 1.00 mpp[tiflash] ",
" │ └─ExchangeSender_14 1.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST",
" │ └─Selection_13 1.00 mpp[tiflash] not(isnull(test.t1.a))",
" │ └─TableFullScan_12 1.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false",
" └─Selection_17(Probe) 8.00 mpp[tiflash] not(isnull(test.t2.b))",
" └─TableFullScan_16 8.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false"
],
"Warn": null
}
]
},
{
"Name": "TestIssue37520",
"Cases": [
Expand Down
14 changes: 12 additions & 2 deletions planner/core/exhaust_physical_plans.go
Original file line number Diff line number Diff line change
Expand Up @@ -2386,8 +2386,18 @@ func (p *LogicalJoin) tryToGetMppHashJoin(prop *property.PhysicalProperty, useBC
preferredBuildIndex = 1
}
} else if p.JoinType.IsSemiJoin() {
preferredBuildIndex = 1
fixedBuildSide = true
if !p.isNAAJ() && len(p.EqualConditions) > 0 && (p.JoinType == SemiJoin || p.JoinType == AntiSemiJoin) {
// TiFlash only supports Non-null_aware non-cross semi/anti_semi join to use both sides as build side
preferredBuildIndex = 1
// MPPOuterJoinFixedBuildSide default value is false
// use MPPOuterJoinFixedBuildSide here as a way to disable using left table as build side
if !p.ctx.GetSessionVars().MPPOuterJoinFixedBuildSide && p.children[1].statsInfo().Count() > p.children[0].statsInfo().Count() {
preferredBuildIndex = 0
}
} else {
preferredBuildIndex = 1
fixedBuildSide = true
}
}
if p.JoinType == LeftOuterJoin || p.JoinType == RightOuterJoin {
// TiFlash does not require that the build side must be the inner table for outer join.
Expand Down