-
Notifications
You must be signed in to change notification settings - Fork 5.9k
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
*: implement index nested loop join #2945
Conversation
plan/physical_plan_builder.go
Outdated
@@ -571,6 +571,205 @@ func (p *Join) convert2PhysicalPlanRight(prop *requiredProperty, innerJoin bool) | |||
return resultInfo, nil | |||
} | |||
|
|||
// buildSelectionWithConds will build a selection use the conditions of join and convert one side's column to correlated column. | |||
// This is called when build nested loop join. | |||
func (p *Join) buildSelectionWithConds(left bool) (*Selection, []*expression.CorrelatedColumn) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
left
is not a good name.
plan/physical_plan_builder.go
Outdated
selection.SetSchema(innerChild.Schema().Clone()) | ||
selection.SetChildren(innerChild) | ||
if left { | ||
conds = make([]expression.Expression, 0, len(p.EqualConditions)+len(p.RightConditions)+len(p.OtherConditions)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you need to resolve again for other condition? add test for it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added
plan/physical_plan_builder.go
Outdated
ap := &PhysicalApply{ | ||
PhysicalJoin: resultInfo.p, | ||
OuterSchema: corCols, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ap.self = ap
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But self
is one part of baseLogicalPlan not one part of basePlan.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well
plan/physical_plan_builder.go
Outdated
join.tp = "NestedLoopJoinLeft" | ||
join.allocator = p.allocator | ||
join.initIDAndContext(p.ctx) | ||
join.SetChildren(lInfo.p, rInfo.p) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
join.self = join
Can we offer a way to choose the outer table of index join ? |
Now we can use hint to choose the outer table. |
LGTM |
executor/join_test.go
Outdated
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", "3 3 3 4", "<nil> <nil> 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.6667")) | ||
|
||
_, err = tk.Exec("select /*+ TIDB_INLJ(t) TIDB_SMJ(t) * from t join t1 on t.a=t1.a") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Syntax error.
plan/physical_plan_builder.go
Outdated
@@ -1004,7 +1246,7 @@ func (p *Union) convert2PhysicalPlan(prop *requiredProperty) (*physicalPlanInfo, | |||
// makeScanController will try to build a selection that controls the below scan's filter condition, | |||
// and return a physicalPlanInfo. If the onlyJudge is true, it will only check whether this selection | |||
// can become a scan controller without building the physical plan. | |||
func (p *Selection) makeScanController(onlyJudge bool) (*physicalPlanInfo, bool) { | |||
func (p *Selection) makeScanController(onlyJudge bool) (*physicalPlanInfo, int) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replace judge
with check
.
plan/physical_plan_builder.go
Outdated
} | ||
ts := &PhysicalTableScan{ | ||
cond, _ := expression.SubstituteCorCol2Constant(expr) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't the condition already been substituted at the beginning of the function?
plan/physical_plan_builder.go
Outdated
} | ||
ts := &PhysicalTableScan{ | ||
// else will judge whether can build a index scan or just build a index scan. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Search the keyword judge
replace them all, include comments.
colMapper: make(map[*ast.ColumnNameExpr]int), | ||
is: is, | ||
} | ||
p := builder.build(stmt) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
combine the line 1129 to 1142 as doOptimize
to avoid the Cache
plan.
plan/physical_plan_builder.go
Outdated
better = better || (chosenPlan.accessEqualCount == is.accessEqualCount && chosenPlan.accessInAndEqCount < is.accessInAndEqCount) | ||
_, _, accessEqualCount, accessInAndEqCount := DetachIndexScanConditions(condsBackUp, idx) | ||
better := chosenPlan == nil || bestEqualCount < accessEqualCount | ||
better = better || (bestEqualCount == accessEqualCount && bestInAndEqCount < accessInAndEqCount) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think simply check access equal count is enough.
better := accessEqualCount >= bestEqualCount
Other wise, we need to add tests for accesInAndEqCount
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
When one of join's children is a scan and there are equal conditions that use the index of this scan. We can build this join to a nested loop join and build this scan using index to look up.
Currently index nested loop join is controlled by the hint
/*+ TIDB_INLJ(t1, t2) */
not cost-based.And only the table in
TIDB_INLJ()
will be considered as outer table of the join.