Skip to content

Commit

Permalink
plan: eliminate tablescan's cost more precisely.
Browse files Browse the repository at this point in the history
  • Loading branch information
hanfei1991 committed Dec 13, 2016
1 parent 9c83f3f commit 8158ae6
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 21 deletions.
4 changes: 4 additions & 0 deletions plan/match_property.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ func (ts *PhysicalTableScan) matchProperty(prop *requiredProperty, infos ...*phy
sortedTS.Desc = prop.props[0].desc
sortedTS.KeepOrder = true
sortedTS.addLimit(prop.limit)
// If there exists a table filter, we should calculate the filter scan cost.
if len(sortedTS.tableFilterConditions) > 0 {
cost += rowCount * cpuFactor
}
p := sortedTS.tryToAddUnionScan(&sortedTS)
return enforceProperty(&requiredProperty{limit: prop.limit}, &physicalPlanInfo{
p: p,
Expand Down
3 changes: 2 additions & 1 deletion plan/physical_plan_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -937,8 +937,9 @@ func (p *Selection) convert2PhysicalPlanPushOrder(prop *requiredProperty) (*phys
if limit != nil && info.p != nil {
if np, ok := info.p.(physicalDistSQLPlan); ok {
np.addLimit(limit)
scanCount := info.count
info.count = limit.Count
info.cost = np.calculateCost(info.count)
info.cost = np.calculateCost(info.count, scanCount)
} else {
info = enforceProperty(&requiredProperty{limit: limit}, info)
}
Expand Down
30 changes: 17 additions & 13 deletions plan/physical_plan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -340,13 +340,17 @@ func (s *testPlanSuite) TestCBO(c *C) {
sql: "select sum(t.a) from t where t.c in (1,2) and t.d in (1,3) group by t.d order by t.d",
best: "Index(t.c_d_e)[[1 1,1 1] [1 3,1 3] [2 1,2 1] [2 3,2 3]]->HashAgg->Sort->Trim",
},
{
sql: "select * from t where t.c = 1 and t.e = 1 order by t.a limit 1",
best: "Index(t.c_d_e)[[1,1]]->Sort + Limit(1) + Offset(0)",
},
{
sql: "select * from t t1 ignore index(e) where c < 0",
best: "Index(t.c_d_e)[[-inf,0)]",
},
{
sql: "select * from t t1 ignore index(c_d_e) where c < 0",
best: "Table(t)->Selection",
best: "Table(t)",
},
{
sql: "select * from t where f in (1,2) and g in(1,2,3,4,5)",
Expand All @@ -373,28 +377,28 @@ func (s *testPlanSuite) TestCBO(c *C) {
best: "LeftHashJoin{Table(t)->Table(t)}(a.c,b.c)->HashAgg->Sort->Trim",
},
{
sql: "select count(*) from t group by c",
best: "Index(t.c_d_e)[[<nil>,+inf]]->StreamAgg",
sql: "select count(*) from t where concat(a,b) = 'abc' group by c",
best: "Index(t.c_d_e)[[<nil>,+inf]]->Selection->StreamAgg",
},
{
sql: "select sum(b.a) from t a , t b where a.c = b.c group by b.d",
best: "LeftHashJoin{Table(t)->Index(t.c_d_e)[[<nil>,+inf]]->StreamAgg}(a.c,b.c)->HashAgg",
sql: "select sum(b.a) from t a, t b where a.c = b.c and cast(b.d as char) group by b.d",
best: "RightHashJoin{Index(t.c_d_e)[[<nil>,+inf]]->Selection->StreamAgg->Table(t)}(b.c,a.c)->HashAgg",
},
{
sql: "select count(*) from t group by e order by d limit 1",
best: "Table(t)->HashAgg->Sort + Limit(1) + Offset(0)->Trim",
},
{
sql: "select count(*) from t group by a",
best: "Table(t)->StreamAgg",
sql: "select count(*) from t where concat(a,b) = 'abc' group by a",
best: "Table(t)->Selection->StreamAgg",
},
{
sql: "select count(*) from t group by a order by a",
best: "Table(t)->StreamAgg->Trim",
sql: "select count(*) from t where concat(a,b) = 'abc' group by a order by a",
best: "Table(t)->Selection->StreamAgg->Trim",
},
{
sql: "select count(distinct e) from t where c = 1 group by d",
best: "Index(t.c_d_e)[[1,1]]->StreamAgg",
sql: "select count(distinct e) from t where c = 1 and concat(c,d) = 'abc' group by d",
best: "Index(t.c_d_e)[[1,1]]->Selection->StreamAgg",
},
{
sql: "select count(distinct e) from t group by d",
Expand Down Expand Up @@ -423,7 +427,7 @@ func (s *testPlanSuite) TestCBO(c *C) {
},
{
sql: "select * from t a where a.c < 10000 order by a.a limit 2",
best: "Index(t.c_d_e)[[-inf,10000)]->Sort + Limit(2) + Offset(0)",
best: "Table(t)",
},
{
sql: "select * from t a where a.c < 10000 and a.d in (1000, a.e) order by a.a limit 2",
Expand Down Expand Up @@ -476,7 +480,7 @@ func (s *testPlanSuite) TestCBO(c *C) {

builder := &planBuilder{
allocator: new(idAllocator),
ctx: mock.NewContext(),
ctx: mockContext(),
colMapper: make(map[*ast.ColumnNameExpr]int),
}
p := builder.build(stmt)
Expand Down
18 changes: 11 additions & 7 deletions plan/physical_plans.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,26 +65,30 @@ type physicalDistSQLPlan interface {
addAggregation(ctx context.Context, agg *PhysicalAggregation) expression.Schema
addTopN(ctx context.Context, prop *requiredProperty) bool
addLimit(limit *Limit)
calculateCost(count uint64) float64
calculateCost(count uint64, scanCount uint64) float64
}

func (p *PhysicalIndexScan) calculateCost(count uint64) float64 {
cnt := float64(count)
func (p *PhysicalIndexScan) calculateCost(resultCount uint64, scanCount uint64) float64 {
// TODO: Eliminate index cost more precisely.
cnt := float64(resultCount)
// network cost
cost := cnt * netWorkFactor
if p.DoubleRead {
cost *= 2
}
// sort cost
if !p.OutOfOrder && p.DoubleRead {
cost += float64(count) * cpuFactor
cost += cnt * cpuFactor
}
return cost
}

func (p *PhysicalTableScan) calculateCost(count uint64) float64 {
cnt := float64(count)
return cnt * netWorkFactor
func (p *PhysicalTableScan) calculateCost(resultCount uint64, scanCount uint64) float64 {
cost := float64(resultCount) * netWorkFactor
if len(p.tableFilterConditions) > 0 {
cost += float64(scanCount) * cpuFactor
}
return cost
}

type physicalTableSource struct {
Expand Down

0 comments on commit 8158ae6

Please sign in to comment.