planner: support push part of order property down to the partition table#36108
planner: support push part of order property down to the partition table#36108ti-chi-bot merged 31 commits intopingcap:masterfrom
Conversation
|
[REVIEW NOTIFICATION] This pull request has been approved by:
To complete the pull request process, please ask the reviewers in the list to review by filling The full list of commands accepted by this bot can be found here. DetailsReviewer can indicate their review by submitting an approval review. |
planner/core/task.go
Outdated
| } | ||
|
|
||
| // If we reach here, the index matches the order property of the top-n, we could push a limit down. | ||
| copTsk.keepOrder = true |
There was a problem hiding this comment.
It seems like we don't need to set copTask.keepOrder to true.
There was a problem hiding this comment.
func buildIndexLookUpTask(ctx sessionctx.Context, t *copTask) *rootTask {
newTask := &rootTask{cst: t.cst}
p := PhysicalIndexLookUpReader{
tablePlan: t.tablePlan,
indexPlan: t.indexPlan,
ExtraHandleCol: t.extraHandleCol,
CommonHandleCols: t.commonHandleCols,
expectedCnt: t.expectCnt,
keepOrder: t.keepOrder,
}.Init(ctx, t.tablePlan.SelectBlockOffset())
This func uses it.
There was a problem hiding this comment.
Oh actually we don't need the keep order, remove it.
planner/core/task.go
Outdated
| return nil, false | ||
| } | ||
| } | ||
| copTsk.keepOrder = true |
| } | ||
| tblScan = finalTblScanPlan.(*PhysicalTableScan) | ||
| } | ||
| if !copTsk.indexPlanFinished { |
There was a problem hiding this comment.
We didn't consider that idxScan might be nil in the logic below.
There was a problem hiding this comment.
When indexPlanFinished is not true, there should be a index scan to be finished later.
| // pushTopNDownToDynamicPartition is a temp solution for partition table. It actually does the same thing as DataSource's isMatchProp. | ||
| func (p *PhysicalTopN) pushTopNDownToDynamicPartition(copTsk *copTask) (task, bool) { |
There was a problem hiding this comment.
I think we need more detailed comments since it's a tricky way to modify the plan.
I think we should clarify what the resulting plan would be like and why we have to use this method as a temporary solution.
| if tblScan.HandleCols.IsInt() { | ||
| pk := tblScan.HandleCols.GetCol(0) | ||
| if len(colsProp.SortItems) != 1 || !colsProp.SortItems[0].Col.Equal(p.SCtx(), pk) { |
There was a problem hiding this comment.
This is different from (*DataSource).isMatchProp. According to isMatchProp, tiflash doesn't support desc scan.
There was a problem hiding this comment.
This change only affects tikv part.
planner/core/task.go
Outdated
| if copTsk.tablePlan != nil && !idxScan.Table.IsCommonHandle && copTsk.extraHandleCol == nil { | ||
| // The clustered index would always add handle, so we don't need to consider that case. | ||
| copTsk.extraHandleCol = &expression.Column{ | ||
| RetType: types.NewFieldType(mysql.TypeLonglong), | ||
| ID: model.ExtraHandleID, | ||
| UniqueID: idxScan.ctx.GetSessionVars().AllocPlanColumnID(), | ||
| } | ||
| tblScan.Schema().Append(copTsk.extraHandleCol) | ||
| tblScan.Columns = append(tblScan.Columns, model.NewExtraHandleColInfo()) | ||
| copTsk.needExtraProj = true | ||
| copTsk.originSchema = idxScan.dataSourceSchema | ||
| } |
There was a problem hiding this comment.
We missed the case that the int primary key is not _tidb_rowid but a column specified by the user.
I think we can modify the (*PhysicalTableScan).appendExtraHandleCol a bit and reuse that.
|
Code Coverage Details: https://codecov.io/github/pingcap/tidb/commit/27324cbb5e663b42207d456b6b59dca30ab37351 |
planner/core/task.go
Outdated
| func (p *PhysicalTopN) pushTopNDownToDynamicPartition(copTsk *copTask) (task, bool) { | ||
| var err error | ||
| copTsk = copTsk.copy().(*copTask) | ||
| if err != nil { |
There was a problem hiding this comment.
the err isn't assigned anything before
planner/core/task.go
Outdated
| } | ||
|
|
||
| // If we reach here, the index matches the order property of the top-n, we could push a limit down. | ||
| copTsk.keepOrder = true |
| if len(constColsByCond) == 0 || idxPos > len(constColsByCond) || !constColsByCond[idxPos] { | ||
| found = false | ||
| break | ||
| } |
There was a problem hiding this comment.
missed set found = true at the end? (indicating that we are sure that this col is constant, then just go to outer's continued column)
In:
order by (a,b,c), once index(a,c) exists and b=1, we can still access this path right?
reader -> limit -> selection -> indexScan
order by (a,c), once index(a,b,c) exists and b=1 is what actually it already does.
3dfbb1f to
7778f01
Compare
7778f01 to
e285406
Compare
| return true | ||
| } | ||
| if len(j) == 0 { | ||
| return false |
There was a problem hiding this comment.
why the len(j) = 0 has different logic with the above?
| valid := false | ||
| for i, tt := range input { | ||
| if tt == "select * from t1 where (id = 1 and a = 1) or a is null" { | ||
| fmt.Println("1") |
planner/core/task.go
Outdated
| return nil, false | ||
| } | ||
| finalTblScanPlan := copTsk.tablePlan | ||
| if len(finalTblScanPlan.Children()) > 0 { |
| } | ||
| tblScan.Desc = isDesc | ||
| childProfile := copTsk.plan().statsInfo() | ||
| newCount := p.Offset + p.Count |
There was a problem hiding this comment.
should we consider there's a selection on the table side? the count here may won't pass the selection
There was a problem hiding this comment.
In such case, the plan should be Limit->Selection->TableScan. The selection should not matter
|
/merge |
|
This pull request has been accepted and is ready to merge. DetailsCommit hash: 953273f |
TiDB MergeCI notify🔴 Bad News! New failing [1] after this pr merged.
|
What problem does this PR solve?
Issue Number: ref #26166 (a quick solution)
Problem Summary:
The partition table shields the partition information in the execution phase. So we cannot convert the
order by index limit xto LIMIT with the order property pushed to the index kv.What is changed and how it works?
This time we don't change the codes of the execution. So we cannot push the full order property down to the index kv.
We just change the plan from
TopN(TiDB)->Reader(TiDB)->TopN(TiKV)->ScanKV(TiKV, no order)toTopN(TiDB)->Reader(TiDB)->Limit(TiKV)->ScanKV(TiKV, in order).Check List
Tests
Side effects
Documentation
Release note
Please refer to Release Notes Language Style Guide to write a quality release note.