Skip to content

Commit

Permalink
Add push the limit down to projection.
Browse files Browse the repository at this point in the history
  • Loading branch information
doggeral committed Dec 26, 2019
1 parent 86ae838 commit 39f43c9
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"name": "TestTopNRules",
"cases": [
"select b from t order by a limit 2",
"select b from t limit 2",
"select a+b from t order by a limit 1 offset 2",
"select c from t order by t.a limit 1",
"select c from t order by t.a + t.b limit 1",
Expand Down
13 changes: 13 additions & 0 deletions planner/cascades/testdata/transformation_rules_suite_out.json
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,19 @@
" TableScan_6 table:t, pk col:test.t.a"
]
},
{
"SQL": "select b from t limit 2",
"Result": [
"Group#0 Schema:[test.t.b]",
" Projection_2 input:[Group#1], test.t.b",
"Group#1 Schema:[test.t.b]",
" Limit_6 input:[Group#2], offset:0, count:2",
"Group#2 Schema:[test.t.b]",
" TiKVSingleGather_5 input:[Group#3], table:t",
"Group#3 Schema:[test.t.b]",
" TableScan_4 table:t"
]
},
{
"SQL": "select a+b from t order by a limit 1 offset 2",
"Result": [
Expand Down
48 changes: 48 additions & 0 deletions planner/cascades/transformation_rules.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ var defaultTransformationMap = map[memo.Operand][]Transformation{
},
memo.OperandLimit: {
NewRuleTransformLimitToTopN(),
NewRulePushLimitDownProjection(),
},
memo.OperandProjection: {
NewRuleEliminateProjection(),
Expand Down Expand Up @@ -665,6 +666,53 @@ func (r *TransformLimitToTopN) OnTransform(old *memo.ExprIter) (newExprs []*memo
return []*memo.GroupExpr{topNExpr}, true, false, nil
}

// PushLimitDownProjection pushes Limit to Projection.
type PushLimitDownProjection struct {
baseRule
}

// NewRulePushLimitDownProjection creates a new Transformation. The pattern of this rule is `Limit->Projection->X` to `Projection->Limit->X`.
func NewRulePushLimitDownProjection() Transformation {
rule := &PushLimitDownProjection{}
rule.pattern = memo.BuildPattern(
memo.OperandLimit,
memo.EngineTiDBOnly,
memo.NewPattern(memo.OperandProjection, memo.EngineTiDBOnly),
)
return rule
}

// Match implements Transformation interface.
func (r *PushLimitDownProjection) Match(expr *memo.ExprIter) bool {
proj := expr.Children[0].GetExpr().ExprNode.(*plannercore.LogicalProjection)
for _, expr := range proj.Exprs {
if expression.HasAssignSetVarFunc(expr) {
return false
}
}
return true
}

// OnTransform implements Transformation interface.
// This rule tries to pushes the Limit through Projection.
func (r *PushLimitDownProjection) OnTransform(old *memo.ExprIter) (newExprs []*memo.GroupExpr, eraseOld bool, eraseAll bool, err error) {
limit := old.GetExpr().ExprNode.(*plannercore.LogicalLimit)
proj := old.Children[0].GetExpr().ExprNode.(*plannercore.LogicalProjection)
childGroup := old.Children[0].GetExpr().Children[0]

newLimit := plannercore.LogicalLimit{
Offset: limit.Offset,
Count: limit.Count,
}.Init(limit.SCtx(), limit.SelectBlockOffset())

projExpr := memo.NewGroupExpr(proj)
limitExpr := memo.NewGroupExpr(newLimit)
limitExpr.SetChildren(childGroup)
limitGroup := memo.NewGroupWithSchema(limitExpr, childGroup.Prop.Schema)
projExpr.SetChildren(limitGroup)
return []*memo.GroupExpr{projExpr}, true, false, nil
}

// PushSelDownJoin pushes Selection through Join.
type PushSelDownJoin struct {
baseRule
Expand Down
1 change: 1 addition & 0 deletions planner/cascades/transformation_rules_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ func (s *testTransformationRuleSuite) TestTopNRules(c *C) {
s.optimizer.ResetTransformationRules(map[memo.Operand][]Transformation{
memo.OperandLimit: {
NewRuleTransformLimitToTopN(),
NewRulePushLimitDownProjection(),
},
memo.OperandDataSource: {
NewRuleEnumeratePaths(),
Expand Down

0 comments on commit 39f43c9

Please sign in to comment.