Skip to content
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: consider limit during building physcial plan. #1760

Merged
merged 10 commits into from
Sep 26, 2016
Merged

Conversation

hanfei1991
Copy link
Member

@hanfei1991 hanfei1991 commented Sep 23, 2016

The purpose of this pr is to push down topn operator.#1746 I change the plan part before supporting it in local store.
@shenli @coocood @zimulala @tiancaiamao @XuHuaiyu PTAL

@@ -25,13 +25,16 @@ func (ts *PhysicalTableScan) matchProperty(prop *requiredProperty, infos ...*phy
rowCount := float64(infos[0].count)
cost := rowCount * netWorkFactor
if len(prop.props) == 0 {
return &physicalPlanInfo{p: ts, cost: cost, count: infos[0].count}
return enforceProperty(prop, &physicalPlanInfo{p: ts, cost: cost, count: infos[0].count})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if len(prop.props) == 0 && prop.limit != nil?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's no need to check whether prop.limit is nil. If it is, it won't change the plan info.

@@ -76,6 +76,8 @@ type Selection struct {
// but after we converted to CNF(Conjunctive normal form), it can be
// split into a list of AND conditions.
Conditions []expression.Expression

aboveTableScan bool
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add comments about this property.

@@ -75,7 +78,7 @@ func (is *PhysicalIndexScan) matchProperty(prop *requiredProperty, infos ...*phy
cost *= 2
}
if len(prop.props) == 0 {
return &physicalPlanInfo{p: is, cost: cost, count: infos[0].count}
return enforceProperty(&requiredProperty{limit: prop.limit}, &physicalPlanInfo{p: is, cost: cost, count: infos[0].count})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Define a limitProperty, it will be used in several places.

return info
}

func removeLimit(prop *requiredProperty, removeAll bool) *requiredProperty {
Copy link
Member

@coocood coocood Sep 23, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add comments about when and why we need to remove limit, and when removeAll need to be false when removeAll need to be true.

sortKeyLen: prop.sortKeyLen,
limit: prop.limit}
if len(prop.props) > 0 {
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfinished or useless?

@hanfei1991
Copy link
Member Author

// removeLimit removes limit from prop. For example, When handling Sort,Limit -> Selection, we can't pass the Limit
// across the selection, because selection decreases the size of data, but we can pass the Sort below the selection. In
// this case, we set removeAll true. When handling Limit(1,1) -> LeftOuterJoin, we can pass the limit across join's left
// path, because the left outer join increases the size of data, but we can't pass offset value. So we set remove All to false.
Copy link
Member

@coocood coocood Sep 23, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So when removeAll is set to false, it's meant to remove offset, then how about define a different function named removeOffset?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Current designment is orthogonal

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't get your point.
It's confusing that removeLimit is not doing what it's supposed to do.
When removeAll is set to false, it doesn't remove limit at all.

@@ -77,6 +77,7 @@ type Selection struct {
// split into a list of AND conditions.
Conditions []expression.Expression

// aboveTableScan means if this selection's child is a table scan or index scan.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So aboveTableScan is false if the selection's child is a join or having? Then above is not accurate, and TableScan doesn't contains IndexScan.
How about onTable?

}
}
err := types.SortDatums(datums)
if err != nil {
return nil, errors.Trace(err)
log.Error(err.Error())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will loss the error.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this error shouldn't make sql fail. Instead, it can forbid this condition to push down.

}
val, err := codec.EncodeValue(nil, datums...)
if err != nil {
return nil, errors.Trace(err)
log.Error(err.Error())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

@@ -325,6 +323,58 @@ func addPlanToResponse(p PhysicalPlan, planInfo *physicalPlanInfo) *physicalPlan
return &physicalPlanInfo{p: np, cost: planInfo.cost, count: planInfo.count}
}

func enforceProperty(prop *requiredProperty, info *physicalPlanInfo) *physicalPlanInfo {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add comment for this.

// removeLimit removes limit from prop. For example, When handling Sort,Limit -> Selection, we can't pass the Limit
// across the selection, because selection decreases the size of data, but we can pass the Sort below the selection. In
// this case, we set removeAll true. When handling Limit(1,1) -> LeftOuterJoin, we can pass the limit across join's left
// path, because the left outer join increases the size of data, but we can't pass offset value. So we set remove All to false.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove All -> removeAll

@@ -677,33 +735,72 @@ func (p *Union) convert2PhysicalPlan(prop *requiredProperty) (*physicalPlanInfo,
childInfos = append(childInfos, info)
}
info = p.matchProperty(prop, childInfos...)
info = enforceProperty(limitProperty(limit), info)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When should we call this function?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should call this function upon every operator that refuses the required property.

info, err := p.getPlanInfo(prop)
if err != nil {
return nil, errors.Trace(err)
}
if info != nil {
return info, nil
}
info, err = p.GetChildByIndex(0).(LogicalPlan).convert2PhysicalPlan(prop)
// Firstly, we try to push order
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a secondly?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will add a "secondly" comment.

}
}

func (p *physicalTableSource) addTopN(prop *requiredProperty) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we support top-n on localstore?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We havn't. I will implement it in next pr.

@hanfei1991
Copy link
Member Author

hanfei1991 commented Sep 26, 2016

@hanfei1991
Copy link
Member Author

PTAL @coocood

@coocood
Copy link
Member

coocood commented Sep 26, 2016

LGTM

@@ -325,6 +323,62 @@ func addPlanToResponse(p PhysicalPlan, planInfo *physicalPlanInfo) *physicalPlan
return &physicalPlanInfo{p: np, cost: planInfo.cost, count: planInfo.count}
}

// enforceProperty add an topN or sort upon current operator.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May thie function add limit upon current operator?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you are right. I will update the comment

}

id := column.ID
// Zero Column ID is not a column from table, can not support for now.
if id == 0 {
return nil, nil
return nil
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if id == 0 || id == -1 { return nil}

@hanfei1991
Copy link
Member Author

@shenli PTAL

@shenli
Copy link
Member

shenli commented Sep 26, 2016

LGTM

@shenli shenli merged commit 471731b into master Sep 26, 2016
@shenli shenli deleted the hanfei/topn branch September 26, 2016 13:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants