diff --git a/plan/cbo_test.go b/plan/cbo_test.go index 63ccd92dbf..d2ebf30153 100644 --- a/plan/cbo_test.go +++ b/plan/cbo_test.go @@ -248,7 +248,7 @@ func (s *testAnalyzeSuite) TestIndexRead(c *C) { }, { sql: "select count(*) from t where e > 1 group by b", - best: "TableReader(Table(t)->Sel([gt(test.t.e, 1)])->HashAgg)->HashAgg", + best: "IndexLookUp(Index(t.b)[[,+inf]], Table(t)->Sel([gt(test.t.e, 1)]))->StreamAgg", }, { sql: "select count(e) from t where t.b <= 20", diff --git a/plan/physical_plan_builder.go b/plan/physical_plan_builder.go index 358825d20c..ba3167f4a2 100644 --- a/plan/physical_plan_builder.go +++ b/plan/physical_plan_builder.go @@ -33,10 +33,13 @@ const ( scanFactor = 2.0 descScanFactor = 5 * scanFactor memoryFactor = 5.0 - hashAggMemFactor = 2.0 + // 0.5 is the looking up agg context factor. + hashAggFactor = 1.2 + 0.5 selectionFactor = 0.8 distinctFactor = 0.8 cpuFactor = 0.9 + distinctAggFactor = 1.6 + createAggCtxFactor = 6 ) // wholeTaskTypes records all possible kinds of task that a plan can return. For Agg, TopN and Limit, we will try to get diff --git a/plan/physical_plans.go b/plan/physical_plans.go index d4be6b151b..f01fe0798c 100644 --- a/plan/physical_plans.go +++ b/plan/physical_plans.go @@ -304,6 +304,15 @@ type basePhysicalAgg struct { GroupByItems []expression.Expression } +func (p *basePhysicalAgg) hasDistinctFunc() bool { + for _, fun := range p.AggFuncs { + if fun.HasDistinct { + return true + } + } + return false +} + // PhysicalHashAgg is hash operator of aggregate. type PhysicalHashAgg struct { basePhysicalAgg diff --git a/plan/task.go b/plan/task.go index 67ebe0c4a7..039db1ec31 100644 --- a/plan/task.go +++ b/plan/task.go @@ -520,10 +520,12 @@ func (p *PhysicalStreamAgg) attach2Task(tasks ...task) task { } t = finishCopTask(p.ctx, cop) attachPlan2Task(finalAgg, t) - t.addCost(t.count() * cpuFactor) } else { attachPlan2Task(p, t) - t.addCost(t.count() * cpuFactor) + } + t.addCost(t.count() * cpuFactor) + if p.hasDistinctFunc() { + t.addCost(t.count() * cpuFactor * distinctAggFactor) } return t } @@ -534,8 +536,8 @@ func (p *PhysicalHashAgg) attach2Task(tasks ...task) task { return invalidTask } cardinality := p.StatsInfo().count - task := tasks[0].copy() - if cop, ok := task.(*copTask); ok { + t := tasks[0].copy() + if cop, ok := t.(*copTask); ok { partialAgg, finalAgg := p.newPartialAggregate() if partialAgg != nil { if cop.tablePlan != nil { @@ -547,12 +549,14 @@ func (p *PhysicalHashAgg) attach2Task(tasks ...task) task { cop.indexPlan = partialAgg } } - task = finishCopTask(p.ctx, cop) - attachPlan2Task(finalAgg, task) - task.addCost(task.count()*cpuFactor + cardinality*hashAggMemFactor) + t = finishCopTask(p.ctx, cop) + attachPlan2Task(finalAgg, t) } else { - attachPlan2Task(p, task) - task.addCost(task.count()*cpuFactor + cardinality*hashAggMemFactor) + attachPlan2Task(p, t) } - return task + t.addCost(t.count()*cpuFactor*hashAggFactor + cardinality*createAggCtxFactor) + if p.hasDistinctFunc() { + t.addCost(t.count() * cpuFactor * distinctAggFactor) + } + return t }