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: support topn push down in plan phase. #1769

Merged
merged 8 commits into from Oct 11, 2016
Merged

plan: support topn push down in plan phase. #1769

merged 8 commits into from Oct 11, 2016

Conversation

hanfei1991
Copy link
Member

It's a additional pr for #1760
It tries to push topn to table scan and index scan.
@coocood @shenli @zimulala @tiancaiamao @XuHuaiyu PTAL

@hanfei1991 hanfei1991 changed the title support topn in plan phase. plan: support topn push down in plan phase. Sep 27, 2016
@coocood
Copy link
Member

coocood commented Sep 27, 2016

Any test covers the case when selection condition can not be converted to PB, then topN will not be pushed?

@@ -114,6 +113,7 @@ func (p *physicalTableSource) addTopN(prop *requiredProperty) {
for _, item := range prop.props {
p.SortItems = append(p.SortItems, sortByItemToPB(p.client, item.col, item.desc))
Copy link
Member

Choose a reason for hiding this comment

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

sortByItem may return nil, then addTopN should return false.

@hanfei1991
Copy link
Member Author

@coocood PTAL

if prop.limit != nil {
count := int64(prop.limit.Count + prop.limit.Offset)
p.LimitCount = &count
if prop.limit == nil || len(prop.props) == 0 {
Copy link
Contributor

@XuHuaiyu XuHuaiyu Sep 28, 2016

Choose a reason for hiding this comment

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

There may be no need to judge "prop.limit == nil", it has been promised before invoking 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.

It's safer to check this again inside this function.

@@ -74,6 +72,7 @@ type physicalTableSource struct {
AggFuncs []*tipb.Expr
GbyItems []*tipb.ByItem

// ConditionPBExpr is the pb structure of conditions that pushed down.
Copy link
Contributor

Choose a reason for hiding this comment

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

pushed down --> be pushed down

@coocood
Copy link
Member

coocood commented Sep 28, 2016

The added test case doesn't make much sense as the test use a mock context which returns a nil Client, and TopN is not supported by local store.
So TopN will never be pushed down.

@hanfei1991
Copy link
Member Author

@coocood PTAL

@@ -373,6 +535,10 @@ func (s *testPlanSuite) TestCBO(c *C) {
best: "Index(t.c_d_e)[[-inf,10000)]->Sort + Limit(2) + Offset(0)->Projection",
},
{
sql: "select * from t a where a.c < 10000 and a.d in (1000, a.e) order by a.a limit 2",
Copy link
Member

Choose a reason for hiding this comment

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

move this case to TestTopnPushDown and verify that top n is not pushed down.

Copy link
Member

Choose a reason for hiding this comment

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

@@ -106,21 +141,38 @@ func (is *PhysicalIndexScan) matchProperty(prop *requiredProperty, infos ...*phy
if allAsc {
Copy link
Contributor

@XuHuaiyu XuHuaiyu Sep 29, 2016

Choose a reason for hiding this comment

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

if allAsc || allDesc{
  if allDesc {
    sortedIs.Desc = true
  }  
 // Duplicated code
}

would this be more brief

Copy link
Member

Choose a reason for hiding this comment

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

@XuHuaiyu
Copy link
Contributor

Please take a look at function handleLeftJoin/handleRightJoin in physical_plan_builder.go, the local variable allLeft/allRight been checked if false three times, but if allLeft/allRight is false, the function will be returned just in the first check, and there is no value write of allLeft/allRight after this check.

selIdxReq.OrderBy = append(selIdxReq.OrderBy, &tipb.ByItem{Desc: e.indexPlan.Desc})
if len(e.indexPlan.SortItems) > 0 {
selIdxReq.OrderBy = e.indexPlan.SortItems
} else if e.indexPlan.Desc {
Copy link
Member

Choose a reason for hiding this comment

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

How about e.indexPlan.SortItems > 0 and e.indexPlan.Desc is true?

Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

If e.indexPlan.SortItems > 0, we don't care if the table is desc scanned or not.

@@ -46,6 +50,10 @@ func (s *testPlanSuite) SetUpSuite(c *C) {
s.Parser = parser.New()
}

func newType() types.FieldType {
Copy link
Contributor

Choose a reason for hiding this comment

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

newTypeLong() be better?

if len(e.orderByList) > 0 {
selReq.OrderBy = e.orderByList
} else if e.supportDesc && e.desc {
selReq.OrderBy = []*tipb.ByItem{{Desc: e.desc}}
Copy link
Member

Choose a reason for hiding this comment

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

{{ -> {

Copy link
Member

Choose a reason for hiding this comment

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

When will e.desc is true and len(e.orderByList) == 0?

Copy link
Member Author

Choose a reason for hiding this comment

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

If no topn is pushed, the order by list will be empty.

if len(prop.props) == 0 {
return enforceProperty(prop, &physicalPlanInfo{p: ts, cost: cost, count: infos[0].count})
p := tryToAddUnionScan(ts.txn, ts.conditions, ts)
Copy link
Member

Choose a reason for hiding this comment

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

Why add union scan here?

Copy link
Member Author

Choose a reason for hiding this comment

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

"try to add union scan" will check if the txn is read-only. If it is, it will add union scan for it.

}
if len(prop.props) == 1 && ts.pkCol != nil && ts.pkCol == prop.props[0].col {
sortedTs := *ts
sortedTs.Desc = prop.props[0].desc
sortedTs.KeepOrder = true
p := tryToAddUnionScan(ts.txn, ts.conditions, &sortedTs)
Copy link
Member

Choose a reason for hiding this comment

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

Should we also addTopN in this condition?

Copy link
Member Author

Choose a reason for hiding this comment

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

This condition means the pk column can match the required property.

@@ -106,21 +141,38 @@ func (is *PhysicalIndexScan) matchProperty(prop *requiredProperty, infos ...*phy
if allAsc {
Copy link
Member

Choose a reason for hiding this comment

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

@@ -259,12 +259,8 @@ func (p *basePlan) initID() {
// basePlan implements base Plan interface.
// Should be used as embedded struct in Plan implementations.
type basePlan struct {
fields []*ast.ResultField
startupCost float64
totalCost float64
Copy link
Member

Choose a reason for hiding this comment

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

These attributes are useless?

Copy link
Member Author

Choose a reason for hiding this comment

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

yeah

@@ -46,6 +50,10 @@ func (s *testPlanSuite) SetUpSuite(c *C) {
s.Parser = parser.New()
}

func newType() types.FieldType {
Copy link
Member

Choose a reason for hiding this comment

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

newLongType is better.

@@ -373,6 +535,10 @@ func (s *testPlanSuite) TestCBO(c *C) {
best: "Index(t.c_d_e)[[-inf,10000)]->Sort + Limit(2) + Offset(0)->Projection",
},
{
sql: "select * from t a where a.c < 10000 and a.d in (1000, a.e) order by a.a limit 2",
Copy link
Member

Choose a reason for hiding this comment

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

@hanfei1991
Copy link
Member Author

@shenli @coocood @XuHuaiyu PTAL

@@ -406,9 +385,6 @@ func (p *Join) handleLeftJoin(prop *requiredProperty, innerJoin bool) (*physical
allLeft = false
}
}
if !allLeft {
Copy link
Member

Choose a reason for hiding this comment

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

Make best effort to push down sort. Because if there is a limit and sort, it will be converted to top-n. Running top-n as early as possible will save running time.

@shenli
Copy link
Member

shenli commented Oct 10, 2016

LGTM

@@ -54,15 +53,14 @@ type PhysicalIndexScan struct {

accessEqualCount int
AccessCondition []expression.Expression
// ConditionPBExpr is the pb structure of conditions that pushed down.
ConditionPBExpr *tipb.Expr
conditions []expression.Expression

TableAsName *model.CIStr
}

type physicalDistSQLPlan interface {
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 about this interface and the methods, describe why we need this interface, how those method should be implemented and used.

@@ -40,7 +39,7 @@ type PhysicalIndexScan struct {
basePlan
physicalTableSource

ctx context.Context
txn kv.Transaction
Copy link
Member

Choose a reason for hiding this comment

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

We don't need to keep a txn reference, we only need to know if it is read only.

@@ -178,7 +179,7 @@ type PhysicalTableScan struct {
basePlan
physicalTableSource

ctx context.Context
txn kv.Transaction
Copy link
Member

Choose a reason for hiding this comment

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

ditto

@coocood
Copy link
Member

coocood commented Oct 11, 2016

LGTM

@hanfei1991 hanfei1991 merged commit 9b9c011 into master Oct 11, 2016
@hanfei1991 hanfei1991 deleted the hanfei/topn branch October 11, 2016 07:17
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.

None yet

5 participants