-
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
planner: adjust estimated row count when pushing Limit
and keep order for partitioned table
#41103
Changes from all commits
86a075b
50860c1
8b4a73a
cebd9f2
afaef54
e0fb05e
66fca04
b397deb
b397535
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 |
---|---|---|
|
@@ -1032,6 +1032,10 @@ func (p *PhysicalTopN) pushTopNDownToDynamicPartition(copTsk *copTask) (task, bo | |
return true | ||
} | ||
var ( | ||
selOnIdxScan *PhysicalSelection | ||
selOnTblScan *PhysicalSelection | ||
selSelectivity float64 | ||
|
||
idxScan *PhysicalIndexScan | ||
tblScan *PhysicalTableScan | ||
tblInfo *model.TableInfo | ||
|
@@ -1044,6 +1048,7 @@ func (p *PhysicalTopN) pushTopNDownToDynamicPartition(copTsk *copTask) (task, bo | |
} | ||
finalIdxScanPlan := copTsk.indexPlan | ||
for len(finalIdxScanPlan.Children()) > 0 && finalIdxScanPlan.Children()[0] != nil { | ||
selOnIdxScan, _ = finalIdxScanPlan.(*PhysicalSelection) | ||
finalIdxScanPlan = finalIdxScanPlan.Children()[0] | ||
} | ||
idxScan = finalIdxScanPlan.(*PhysicalIndexScan) | ||
|
@@ -1056,12 +1061,21 @@ func (p *PhysicalTopN) pushTopNDownToDynamicPartition(copTsk *copTask) (task, bo | |
} | ||
finalTblScanPlan := copTsk.tablePlan | ||
for len(finalTblScanPlan.Children()) > 0 { | ||
selOnTblScan, _ = finalTblScanPlan.(*PhysicalSelection) | ||
finalTblScanPlan = finalTblScanPlan.Children()[0] | ||
} | ||
tblScan = finalTblScanPlan.(*PhysicalTableScan) | ||
tblInfo = tblScan.Table | ||
} | ||
|
||
// Note that we only need to care about one Selection at most. | ||
if selOnIdxScan != nil && idxScan.statsInfo().RowCount > 0 { | ||
selSelectivity = selOnIdxScan.statsInfo().RowCount / idxScan.statsInfo().RowCount | ||
} | ||
if idxScan == nil && selOnTblScan != nil && tblScan.statsInfo().RowCount > 0 { | ||
selSelectivity = selOnTblScan.statsInfo().RowCount / tblScan.statsInfo().RowCount | ||
} | ||
|
||
pi := tblInfo.GetPartitionInfo() | ||
if pi == nil { | ||
return nil, false | ||
|
@@ -1083,6 +1097,17 @@ func (p *PhysicalTopN) pushTopNDownToDynamicPartition(copTsk *copTask) (task, bo | |
}.Init(p.SCtx(), stats, p.SelectBlockOffset()) | ||
pushedLimit.SetSchema(copTsk.indexPlan.Schema()) | ||
copTsk = attachPlan2Task(pushedLimit, copTsk).(*copTask) | ||
|
||
// A similar but simplified logic compared the ExpectedCnt handling logic in getOriginalPhysicalIndexScan. | ||
child := pushedLimit.Children()[0] | ||
// The row count of the direct child of Limit should be adjusted to be no larger than the Limit.Count. | ||
child.SetStats(child.statsInfo().ScaleByExpectCnt(float64(newCount))) | ||
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 can call 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. if the stats are not ref-ed by another OP, just ScaleByExpectCnt is ok. 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.
No. It won't change itself. |
||
// The Limit->Selection->IndexScan case: | ||
// adjust the row count of IndexScan according to the selectivity of the Selection. | ||
if selSelectivity > 0 && selSelectivity < 1 { | ||
scaledRowCount := child.Stats().RowCount / selSelectivity | ||
idxScan.SetStats(idxScan.Stats().ScaleByExpectCnt(scaledRowCount)) | ||
} | ||
} else if copTsk.indexPlan == nil { | ||
if tblScan.HandleCols == nil { | ||
return nil, false | ||
|
@@ -1111,6 +1136,17 @@ func (p *PhysicalTopN) pushTopNDownToDynamicPartition(copTsk *copTask) (task, bo | |
}.Init(p.SCtx(), stats, p.SelectBlockOffset()) | ||
pushedLimit.SetSchema(copTsk.tablePlan.Schema()) | ||
copTsk = attachPlan2Task(pushedLimit, copTsk).(*copTask) | ||
|
||
// A similar but simplified logic compared the ExpectedCnt handling logic in getOriginalPhysicalTableScan. | ||
child := pushedLimit.Children()[0] | ||
// The row count of the direct child of Limit should be adjusted to be no larger than the Limit.Count. | ||
child.SetStats(child.statsInfo().ScaleByExpectCnt(float64(newCount))) | ||
// The Limit->Selection->TableScan case: | ||
// adjust the row count of IndexScan according to the selectivity of the Selection. | ||
if selSelectivity > 0 && selSelectivity < 1 { | ||
scaledRowCount := child.Stats().RowCount / selSelectivity | ||
tblScan.SetStats(tblScan.Stats().ScaleByExpectCnt(scaledRowCount)) | ||
} | ||
} else { | ||
return nil, false | ||
} | ||
|
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.
only care about specified tree type?
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.
Yes. From the current implementation, the only thing that could possibly be here is a
Selection
.@winoros can you verify this?
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.
yes