@@ -877,10 +877,12 @@ func (p *PhysicalLimit) attach2Task(tasks ...task) task {
877
877
} else if ! cop .idxMergeIsIntersection {
878
878
// We only support push part of the order prop down to index merge build case.
879
879
if len (cop .rootTaskConds ) == 0 {
880
- if cop .indexPlanFinished {
881
- // when the index plan is finished, sink the limit to the index merge table side.
880
+ // For double read which requires order being kept, the limit cannot be pushed down to the table side,
881
+ // because handles would be reordered before being sent to table scan.
882
+ if cop .indexPlanFinished && ! cop .keepOrder {
883
+ // when the index plan is finished and index plan is not ordered, sink the limit to the index merge table side.
882
884
suspendLimitAboveTablePlan ()
883
- } else {
885
+ } else if ! cop . indexPlanFinished {
884
886
// cop.indexPlanFinished = false indicates the table side is a pure table-scan, sink the limit to the index merge index side.
885
887
newCount := p .Offset + p .Count
886
888
limitChildren := make ([]PhysicalPlan , 0 , len (cop .idxMergePartPlans ))
@@ -895,6 +897,10 @@ func (p *PhysicalLimit) attach2Task(tasks ...task) task {
895
897
cop .idxMergePartPlans = limitChildren
896
898
t = cop .convertToRootTask (p .SCtx ())
897
899
sunk = p .sinkIntoIndexMerge (t )
900
+ } else {
901
+ // when there are some limitations, just sink the limit upon the index merge reader.
902
+ t = cop .ConvertToRootTask (p .SCtx ())
903
+ sunk = p .sinkIntoIndexMerge (t )
898
904
}
899
905
} else {
900
906
// when there are some root conditions, just sink the limit upon the index merge reader.
0 commit comments