-
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
plan: change the logic of converting to index join #7553
Changes from 6 commits
12f15f5
ba95297
8e64ea1
023f228
968f347
5c9e133
0ed34a2
e486247
90b6937
92a5034
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -518,7 +518,7 @@ func (p *LogicalJoin) buildRangeForIndexJoin(indexInfo *model.IndexInfo, innerPl | |
return nil, nil, nil | ||
} | ||
|
||
conds, eqConds, keyOff2IdxOff := p.buildFakeEqCondsForIndexJoin(innerJoinKeys, idxCols, colLengths, innerPlan) | ||
access, eqConds, remained, keyOff2IdxOff := p.buildFakeEqCondsForIndexJoin(innerJoinKeys, idxCols, colLengths, innerPlan.pushedDownConds) | ||
|
||
if len(keyOff2IdxOff) == 0 { | ||
return nil, nil, nil | ||
|
@@ -527,7 +527,7 @@ func (p *LogicalJoin) buildRangeForIndexJoin(indexInfo *model.IndexInfo, innerPl | |
// After constant propagation, there won'be cases that t1.a=t2.a and t2.a=1 occur in the same time. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we need to update this comment? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. updated There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems it was not updated. |
||
// And if there're cases like t1.a=t2.a and t1.a > 1, we can also guarantee that t1.a > 1 won't be chosen as access condition. | ||
// So DetachCondAndBuildRangeForIndex won't miss the equal conditions we generate. | ||
ranges, accesses, remained, _, err := ranger.DetachCondAndBuildRangeForIndex(p.ctx, conds, idxCols, colLengths) | ||
ranges, accesses, moreRemained, _, err := ranger.DetachCondAndBuildRangeForIndex(p.ctx, access, idxCols, colLengths) | ||
if err != nil { | ||
terror.Log(errors.Trace(err)) | ||
return nil, nil, nil | ||
|
@@ -540,36 +540,48 @@ func (p *LogicalJoin) buildRangeForIndexJoin(indexInfo *model.IndexInfo, innerPl | |
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. when will There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
} | ||
|
||
return ranges, remained, keyOff2IdxOff | ||
return ranges, append(remained, moreRemained...), keyOff2IdxOff | ||
} | ||
|
||
func (p *LogicalJoin) buildFakeEqCondsForIndexJoin(keys, idxCols []*expression.Column, colLengths []int, | ||
innerPlan *DataSource) (accesses, eqConds []expression.Expression, keyOff2IdxOff []int) { | ||
innerFilters []expression.Expression) (accesses, eqConds, remained []expression.Expression, keyOff2IdxOff []int) { | ||
// Check whether all join keys match one column from index. | ||
keyOff2IdxOff = joinKeysMatchIndex(keys, idxCols, colLengths) | ||
if keyOff2IdxOff == nil { | ||
return nil, nil, nil | ||
return nil, nil, nil, nil | ||
} | ||
|
||
usableKeys := make([]*expression.Column, 0, len(keys)) | ||
|
||
// After predicate push down, the one side conditions of join must be the conditions that cannot be pushed down and | ||
// cannot calculate range either. So we only need the innerPlan.pushedDownConds and the eq conditions that we generate. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment should be updated, no |
||
// TODO: There may be a selection that block the index join. | ||
conds := make([]expression.Expression, 0, len(keys)+len(innerPlan.pushedDownConds)) | ||
conds := make([]expression.Expression, 0, len(keys)+len(innerFilters)) | ||
eqConds = make([]expression.Expression, 0, len(keys)) | ||
// Construct a fake equal expression for calculating the range. | ||
for i, key := range keys { | ||
if keyOff2IdxOff[i] < 0 { | ||
continue | ||
} | ||
usableKeys = append(usableKeys, key) | ||
// Int datum 1 can convert to all column's type(numeric type, string type, json, time type, enum, set) safely. | ||
fakeConstant := &expression.Constant{Value: types.NewIntDatum(1), RetType: key.GetType()} | ||
eqFunc := expression.NewFunctionInternal(p.ctx, ast.EQ, types.NewFieldType(mysql.TypeTiny), key, fakeConstant) | ||
conds = append(conds, eqFunc) | ||
eqConds = append(eqConds, eqFunc) | ||
} | ||
|
||
conds = append(conds, innerPlan.pushedDownConds...) | ||
return conds, eqConds, keyOff2IdxOff | ||
remained = make([]expression.Expression, 0, len(innerFilters)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We may need a comment for this code block. |
||
for _, filter := range innerFilters { | ||
affectedCols := expression.ExtractColumns(filter) | ||
if expression.ColumnSliceIsIntersect(affectedCols, usableKeys) { | ||
remained = append(remained, filter) | ||
continue | ||
} | ||
conds = append(conds, filter) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since this filter doesn't contain the column of join keys, can we just move all the filters in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. t1.a=t2.a and t1.b=1 index is (a, b). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. got it. |
||
} | ||
|
||
return conds, eqConds, remained, keyOff2IdxOff | ||
} | ||
|
||
// tryToGetIndexJoin will get index join by hints. If we can generate a valid index join by hint, the second return value | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -407,6 +407,10 @@ func (s *testPlanSuite) TestDAGPlanBuilderJoin(c *C) { | |
sql: "select /*+ TIDB_INLJ(t1) */ * 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)", | ||
best: "IndexJoin{TableReader(Table(t))->TableReader(Table(t)->Sel([in(t2.a, 1, 2)]))}(t1.a,t2.a)", | ||
}, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems like this test sql would not trigger the code path of this patch, i.e, |
||
} | ||
for i, tt := range tests { | ||
comment := Commentf("case:%v sql:%s", i, tt.sql) | ||
|
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.
UniqueID is changed to int64 in #7385, should modify the map definition here.