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: change some function names to improve code readability #6270

Merged
merged 7 commits into from
Apr 12, 2018
30 changes: 15 additions & 15 deletions plan/gen_physical_plans.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import (
"github.com/pingcap/tidb/util/ranger"
)

func (p *LogicalUnionScan) genPhysPlansByReqProp(prop *requiredProp) []PhysicalPlan {
func (p *LogicalUnionScan) exhaustPhysicalPlans(prop *requiredProp) []PhysicalPlan {
us := PhysicalUnionScan{Conditions: p.conditions}.init(p.ctx, p.stats, prop)
return []PhysicalPlan{us}
}
Expand Down Expand Up @@ -405,7 +405,7 @@ func (p *LogicalJoin) tryToGetIndexJoin(prop *requiredProp) ([]PhysicalPlan, boo
// Firstly we check the hint, if hint is figured by user, we force to choose the corresponding physical plan.
// If the hint is not matched, it will get other candidates.
// If the hint is not figured, we will pick all candidates.
func (p *LogicalJoin) genPhysPlansByReqProp(prop *requiredProp) []PhysicalPlan {
func (p *LogicalJoin) exhaustPhysicalPlans(prop *requiredProp) []PhysicalPlan {
mergeJoins := p.getMergeJoin(prop)
if (p.preferJoinType&preferMergeJoin) > 0 && len(mergeJoins) > 0 {
return mergeJoins
Expand Down Expand Up @@ -447,7 +447,7 @@ func (p *LogicalProjection) tryToGetChildProp(prop *requiredProp) (*requiredProp
return newProp, true
}

func (p *LogicalProjection) genPhysPlansByReqProp(prop *requiredProp) []PhysicalPlan {
func (p *LogicalProjection) exhaustPhysicalPlans(prop *requiredProp) []PhysicalPlan {
newProp, ok := p.tryToGetChildProp(prop)
if !ok {
return nil
Expand Down Expand Up @@ -493,14 +493,14 @@ func (lt *LogicalTopN) getPhysLimits() []PhysicalPlan {
return ret
}

func (lt *LogicalTopN) genPhysPlansByReqProp(prop *requiredProp) []PhysicalPlan {
func (lt *LogicalTopN) exhaustPhysicalPlans(prop *requiredProp) []PhysicalPlan {
if prop.matchItems(lt.ByItems) {
return append(lt.getPhysTopN(), lt.getPhysLimits()...)
}
return nil
}

func (la *LogicalApply) genPhysPlansByReqProp(prop *requiredProp) []PhysicalPlan {
func (la *LogicalApply) exhaustPhysicalPlans(prop *requiredProp) []PhysicalPlan {
if !prop.allColsFromSchema(la.children[0].Schema()) { // for convenient, we don't pass through any prop
return nil
}
Expand All @@ -516,8 +516,8 @@ func (la *LogicalApply) genPhysPlansByReqProp(prop *requiredProp) []PhysicalPlan
return []PhysicalPlan{apply}
}

// genPhysPlansByReqProp is only for implementing interface. DataSource and Dual generate task in `convert2PhysicalPlan` directly.
func (p *baseLogicalPlan) genPhysPlansByReqProp(_ *requiredProp) []PhysicalPlan {
// exhaustPhysicalPlans is only for implementing interface. DataSource and Dual generate task in `findBestTask` directly.
func (p *baseLogicalPlan) exhaustPhysicalPlans(_ *requiredProp) []PhysicalPlan {
panic("This function should not be called")
}

Expand Down Expand Up @@ -584,7 +584,7 @@ func (la *LogicalAggregation) getHashAggs(prop *requiredProp) []PhysicalPlan {
return hashAggs
}

func (la *LogicalAggregation) genPhysPlansByReqProp(prop *requiredProp) []PhysicalPlan {
func (la *LogicalAggregation) exhaustPhysicalPlans(prop *requiredProp) []PhysicalPlan {
aggs := make([]PhysicalPlan, 0, len(la.possibleProperties)+1)
aggs = append(aggs, la.getHashAggs(prop)...)

Expand All @@ -594,14 +594,14 @@ func (la *LogicalAggregation) genPhysPlansByReqProp(prop *requiredProp) []Physic
return aggs
}

func (p *LogicalSelection) genPhysPlansByReqProp(prop *requiredProp) []PhysicalPlan {
func (p *LogicalSelection) exhaustPhysicalPlans(prop *requiredProp) []PhysicalPlan {
sel := PhysicalSelection{
Conditions: p.Conditions,
}.init(p.ctx, p.stats.scaleByExpectCnt(prop.expectedCnt), prop)
return []PhysicalPlan{sel}
}

func (p *LogicalLimit) genPhysPlansByReqProp(prop *requiredProp) []PhysicalPlan {
func (p *LogicalLimit) exhaustPhysicalPlans(prop *requiredProp) []PhysicalPlan {
if !prop.isEmpty() {
return nil
}
Expand All @@ -618,14 +618,14 @@ func (p *LogicalLimit) genPhysPlansByReqProp(prop *requiredProp) []PhysicalPlan
return ret
}

func (p *LogicalLock) genPhysPlansByReqProp(prop *requiredProp) []PhysicalPlan {
func (p *LogicalLock) exhaustPhysicalPlans(prop *requiredProp) []PhysicalPlan {
lock := PhysicalLock{
Lock: p.Lock,
}.init(p.ctx, p.stats.scaleByExpectCnt(prop.expectedCnt), prop)
return []PhysicalPlan{lock}
}

func (p *LogicalUnionAll) genPhysPlansByReqProp(prop *requiredProp) []PhysicalPlan {
func (p *LogicalUnionAll) exhaustPhysicalPlans(prop *requiredProp) []PhysicalPlan {
// TODO: UnionAll can not pass any order, but we can change it to sort merge to keep order.
if !prop.isEmpty() {
return nil
Expand Down Expand Up @@ -653,7 +653,7 @@ func (ls *LogicalSort) getNominalSort(reqProp *requiredProp) *NominalSort {
return ps
}

func (ls *LogicalSort) genPhysPlansByReqProp(prop *requiredProp) []PhysicalPlan {
func (ls *LogicalSort) exhaustPhysicalPlans(prop *requiredProp) []PhysicalPlan {
if prop.matchItems(ls.ByItems) {
ret := make([]PhysicalPlan, 0, 2)
ret = append(ret, ls.getPhysicalSort(prop))
Expand All @@ -666,7 +666,7 @@ func (ls *LogicalSort) genPhysPlansByReqProp(prop *requiredProp) []PhysicalPlan
return nil
}

func (p *LogicalExists) genPhysPlansByReqProp(prop *requiredProp) []PhysicalPlan {
func (p *LogicalExists) exhaustPhysicalPlans(prop *requiredProp) []PhysicalPlan {
if !prop.isEmpty() {
return nil
}
Expand All @@ -675,7 +675,7 @@ func (p *LogicalExists) genPhysPlansByReqProp(prop *requiredProp) []PhysicalPlan
return []PhysicalPlan{exists}
}

func (p *LogicalMaxOneRow) genPhysPlansByReqProp(prop *requiredProp) []PhysicalPlan {
func (p *LogicalMaxOneRow) exhaustPhysicalPlans(prop *requiredProp) []PhysicalPlan {
if !prop.isEmpty() {
return nil
}
Expand Down
2 changes: 1 addition & 1 deletion plan/optimizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ func logicalOptimize(flag uint64, logic LogicalPlan) (LogicalPlan, error) {
func physicalOptimize(logic LogicalPlan) (PhysicalPlan, error) {
logic.preparePossibleProperties()
logic.deriveStats()
t, err := logic.convert2PhysicalPlan(&requiredProp{taskTp: rootTaskType, expectedCnt: math.MaxFloat64})
t, err := logic.findBestTask(&requiredProp{taskTp: rootTaskType, expectedCnt: math.MaxFloat64})
if err != nil {
return nil, errors.Trace(err)
}
Expand Down
61 changes: 31 additions & 30 deletions plan/physical_plan_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func getPropByOrderByItems(items []*ByItems) (*requiredProp, bool) {
return &requiredProp{cols: cols, desc: desc}, true
}

func (p *LogicalTableDual) convert2PhysicalPlan(prop *requiredProp) (task, error) {
func (p *LogicalTableDual) findBestTask(prop *requiredProp) (task, error) {
if !prop.isEmpty() {
return invalidTask, nil
}
Expand All @@ -76,43 +76,44 @@ func (p *LogicalTableDual) convert2PhysicalPlan(prop *requiredProp) (task, error
return &rootTask{p: dual}, nil
}

// convert2PhysicalPlan implements LogicalPlan interface.
func (p *baseLogicalPlan) convert2PhysicalPlan(prop *requiredProp) (t task, err error) {
// findBestTask implements LogicalPlan interface.
func (p *baseLogicalPlan) findBestTask(prop *requiredProp) (bestTask task, err error) {
// Look up the task with this prop in the task map.
// It's used to reduce double counting.
t = p.getTask(prop)
if t != nil {
return t, nil
bestTask = p.getTask(prop)
if bestTask != nil {
return bestTask, nil
}
t = invalidTask

if prop.taskTp != rootTaskType {
// Currently all plan cannot totally push down.
p.storeTask(prop, t)
return t, nil
p.storeTask(prop, invalidTask)
return invalidTask, nil
}
for _, pp := range p.self.genPhysPlansByReqProp(prop) {
t, err = p.getBestTask(t, pp)
if err != nil {
return nil, errors.Trace(err)

bestTask = invalidTask
childTasks := make([]task, 0, len(p.children))
for _, pp := range p.self.exhaustPhysicalPlans(prop) {
// find best child tasks firstly.
childTasks = childTasks[:0]
for i, child := range p.children {
childTask, err := child.findBestTask(pp.getChildReqProps(i))
if err != nil {
return nil, errors.Trace(err)
}
childTasks = append(childTasks, childTask)
}
}
p.storeTask(prop, t)
return t, nil
}

func (p *baseLogicalPlan) getBestTask(bestTask task, pp PhysicalPlan) (task, error) {
tasks := make([]task, 0, len(p.children))
for i, child := range p.children {
childTask, err := child.convert2PhysicalPlan(pp.getChildReqProps(i))
if err != nil {
return nil, errors.Trace(err)
// combine best child tasks with parent physical plan.
curTask := pp.attach2Task(childTasks...)

// get the most efficient one.
if curTask.cost() < bestTask.cost() {
bestTask = curTask
}
tasks = append(tasks, childTask)
}
resultTask := pp.attach2Task(tasks...)
if resultTask.cost() < bestTask.cost() {
bestTask = resultTask
}

p.storeTask(prop, bestTask)
return bestTask, nil
}

Expand Down Expand Up @@ -169,9 +170,9 @@ func (ds *DataSource) tryToGetDualTask() (task, error) {
return nil, nil
}

// convert2PhysicalPlan implements the PhysicalPlan interface.
// findBestTask implements the PhysicalPlan interface.
// It will enumerate all the available indices and choose a plan with least cost.
func (ds *DataSource) convert2PhysicalPlan(prop *requiredProp) (task, error) {
func (ds *DataSource) findBestTask(prop *requiredProp) (task, error) {
// If ds is an inner plan in an IndexJoin, the IndexJoin will generate an inner plan by itself.
// So here we do nothing.
// TODO: Add a special prop to handle IndexJoin's inner plan.
Expand Down
8 changes: 4 additions & 4 deletions plan/plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,11 +148,11 @@ type LogicalPlan interface {
// PruneColumns prunes the unused columns.
PruneColumns([]*expression.Column)

// convert2PhysicalPlan converts the logical plan to the physical plan. It's a new interface.
// findBestTask converts the logical plan to the physical plan. It's a new interface.
// It is called recursively from the parent to the children to create the result physical plan.
// Some logical plans will convert the children to the physical plans in different ways, and return the one
// with the lowest cost.
convert2PhysicalPlan(prop *requiredProp) (task, error)
findBestTask(prop *requiredProp) (task, error)

// buildKeyInfo will collect the information of unique keys into schema.
buildKeyInfo()
Expand All @@ -169,8 +169,8 @@ type LogicalPlan interface {
// so we can prepare possible properties for every LogicalPlan node.
preparePossibleProperties() [][]*expression.Column

// genPhysPlansByReqProp generates all possible plans that can match the required property.
genPhysPlansByReqProp(*requiredProp) []PhysicalPlan
// exhaustPhysicalPlans generates all possible plans that can match the required property.
exhaustPhysicalPlans(*requiredProp) []PhysicalPlan

extractCorrelatedCols() []*expression.CorrelatedColumn

Expand Down
21 changes: 13 additions & 8 deletions plan/property_cols_prune.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,28 @@ import (
"github.com/pingcap/tidb/expression"
)

func (ds *DataSource) preparePossibleProperties() (result [][]*expression.Column) {
func (ds *DataSource) preparePossibleProperties() [][]*expression.Column {
indices := ds.availableIndices.indices
includeTS := ds.availableIndices.includeTableScan

result := make([][]*expression.Column, 0, len(indices))
ds.relevantIndices = make([]bool, len(indices))

if includeTS {
col := ds.getPKIsHandleCol()
if col != nil {
result = append(result, []*expression.Column{col})
}

cols := expression.ExtractColumnsFromExpressions(make([]*expression.Column, 0, 10), ds.pushedDownConds, nil)
colsSet := make(map[string]struct{}, len(cols))
for _, col := range cols {
colsSet[col.ColName.L] = struct{}{}
}

for i, idx := range indices {
for _, col := range cols {
if col.ColName.L == idx.Columns[0].Name.L {
ds.relevantIndices[i] = true
break
}
}
_, ok := colsSet[idx.Columns[0].Name.L]
ds.relevantIndices[i] = ok
}
} else {
for i := range ds.relevantIndices {
Expand All @@ -46,7 +51,7 @@ func (ds *DataSource) preparePossibleProperties() (result [][]*expression.Column
result = append(result, cols)
}
}
return
return result
}

func (p *LogicalSelection) preparePossibleProperties() (result [][]*expression.Column) {
Expand Down
55 changes: 23 additions & 32 deletions plan/stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,19 +75,24 @@ func (p *LogicalTableDual) deriveStats() *statsInfo {
}

func (p *baseLogicalPlan) deriveStats() *statsInfo {
if len(p.children) == 0 {
profile := &statsInfo{
count: float64(1),
cardinality: make([]float64, p.self.Schema().Len()),
}
for i := range profile.cardinality {
profile.cardinality[i] = float64(1)
}
p.stats = profile
return profile
if len(p.children) > 1 {
panic("LogicalPlans with more than one child should implement their own deriveStats().")
}
p.stats = p.children[0].deriveStats()
return p.stats

if len(p.children) == 1 {
p.stats = p.children[0].deriveStats()
return p.stats
}

profile := &statsInfo{
count: float64(1),
cardinality: make([]float64, p.self.Schema().Len()),
}
for i := range profile.cardinality {
profile.cardinality[i] = float64(1)
}
p.stats = profile
return profile
}

func (ds *DataSource) getStatsByFilter(conds expression.CNFExprs) *statsInfo {
Expand Down Expand Up @@ -145,35 +150,23 @@ func (p *LogicalUnionAll) deriveStats() *statsInfo {
func (p *LogicalLimit) deriveStats() *statsInfo {
childProfile := p.children[0].deriveStats()
p.stats = &statsInfo{
count: float64(p.Count),
count: math.Min(float64(p.Count), childProfile.count),
cardinality: make([]float64, len(childProfile.cardinality)),
}
if p.stats.count > childProfile.count {
p.stats.count = childProfile.count
}
for i := range p.stats.cardinality {
p.stats.cardinality[i] = childProfile.cardinality[i]
if p.stats.cardinality[i] > p.stats.count {
p.stats.cardinality[i] = p.stats.count
}
p.stats.cardinality[i] = math.Min(childProfile.cardinality[i], p.stats.count)
}
return p.stats
}

func (lt *LogicalTopN) deriveStats() *statsInfo {
childProfile := lt.children[0].deriveStats()
lt.stats = &statsInfo{
count: float64(lt.Count),
count: math.Min(float64(lt.Count), childProfile.count),
cardinality: make([]float64, len(childProfile.cardinality)),
}
if lt.stats.count > childProfile.count {
lt.stats.count = childProfile.count
}
for i := range lt.stats.cardinality {
lt.stats.cardinality[i] = childProfile.cardinality[i]
if lt.stats.cardinality[i] > lt.stats.count {
lt.stats.cardinality[i] = lt.stats.count
}
lt.stats.cardinality[i] = math.Min(childProfile.cardinality[i], lt.stats.count)
}
return lt.stats
}
Expand All @@ -188,10 +181,8 @@ func getCardinality(cols []*expression.Column, schema *expression.Schema, profil
}
var cardinality = 1.0
for _, idx := range indices {
if cardinality < profile.cardinality[idx] {
// It is a very elementary estimation.
cardinality = profile.cardinality[idx]
}
// It is a very elementary estimation.
cardinality = math.Max(cardinality, profile.cardinality[idx])
}
return cardinality
}
Expand Down