Skip to content

Commit

Permalink
plan: always chose the smaller child as outer for IndexJoin (#7019) (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
zz-jason authored Aug 2, 2018
1 parent 13d711f commit f7edb2b
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 83 deletions.
35 changes: 21 additions & 14 deletions plan/gen_physical_plans.go
Original file line number Diff line number Diff line change
Expand Up @@ -385,22 +385,29 @@ func (p *LogicalJoin) tryToGetIndexJoin(prop *requiredProp) ([]PhysicalPlan, boo
plans = append(plans, join...)
}
case InnerJoin:
join := p.getIndexJoinByOuterIdx(prop, 0)
if join != nil {
// If the plan is not nil and matches the hint, return it directly.
if leftOuter {
return join, true
}
plans = append(plans, join...)
lhsCardinality := p.Children()[0].StatsInfo().Count()
rhsCardinality := p.Children()[1].StatsInfo().Count()

leftJoins := p.getIndexJoinByOuterIdx(prop, 0)
if leftOuter && leftJoins != nil {
return leftJoins, true
}
join = p.getIndexJoinByOuterIdx(prop, 1)
if join != nil {
// If the plan is not nil and matches the hint, return it directly.
if rightOuter {
return join, true
}
plans = append(plans, join...)

rightJoins := p.getIndexJoinByOuterIdx(prop, 1)
if rightOuter && rightJoins != nil {
return rightJoins, true
}

if leftJoins != nil && lhsCardinality < rhsCardinality {
return leftJoins, leftOuter
}

if rightJoins != nil && rhsCardinality < lhsCardinality {
return rightJoins, rightOuter
}

plans = append(plans, leftJoins...)
plans = append(plans, rightJoins...)
}
return plans, false
}
Expand Down
38 changes: 19 additions & 19 deletions plan/initialize.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ func (p LogicalSelection) init(ctx sessionctx.Context) *LogicalSelection {
return &p
}

func (p PhysicalSelection) init(ctx sessionctx.Context, stats *statsInfo, props ...*requiredProp) *PhysicalSelection {
func (p PhysicalSelection) init(ctx sessionctx.Context, stats *StatsInfo, props ...*requiredProp) *PhysicalSelection {
p.basePhysicalPlan = newBasePhysicalPlan(ctx, TypeSel, &p)
p.childrenReqProps = props
p.stats = stats
Expand All @@ -122,7 +122,7 @@ func (p LogicalProjection) init(ctx sessionctx.Context) *LogicalProjection {
return &p
}

func (p PhysicalProjection) init(ctx sessionctx.Context, stats *statsInfo, props ...*requiredProp) *PhysicalProjection {
func (p PhysicalProjection) init(ctx sessionctx.Context, stats *StatsInfo, props ...*requiredProp) *PhysicalProjection {
p.basePhysicalPlan = newBasePhysicalPlan(ctx, TypeProj, &p)
p.childrenReqProps = props
p.stats = stats
Expand All @@ -134,7 +134,7 @@ func (p LogicalUnionAll) init(ctx sessionctx.Context) *LogicalUnionAll {
return &p
}

func (p PhysicalUnionAll) init(ctx sessionctx.Context, stats *statsInfo, props ...*requiredProp) *PhysicalUnionAll {
func (p PhysicalUnionAll) init(ctx sessionctx.Context, stats *StatsInfo, props ...*requiredProp) *PhysicalUnionAll {
p.basePhysicalPlan = newBasePhysicalPlan(ctx, TypeUnion, &p)
p.childrenReqProps = props
p.stats = stats
Expand All @@ -146,7 +146,7 @@ func (ls LogicalSort) init(ctx sessionctx.Context) *LogicalSort {
return &ls
}

func (p PhysicalSort) init(ctx sessionctx.Context, stats *statsInfo, props ...*requiredProp) *PhysicalSort {
func (p PhysicalSort) init(ctx sessionctx.Context, stats *StatsInfo, props ...*requiredProp) *PhysicalSort {
p.basePhysicalPlan = newBasePhysicalPlan(ctx, TypeSort, &p)
p.childrenReqProps = props
p.stats = stats
Expand All @@ -164,7 +164,7 @@ func (lt LogicalTopN) init(ctx sessionctx.Context) *LogicalTopN {
return &lt
}

func (p PhysicalTopN) init(ctx sessionctx.Context, stats *statsInfo, props ...*requiredProp) *PhysicalTopN {
func (p PhysicalTopN) init(ctx sessionctx.Context, stats *StatsInfo, props ...*requiredProp) *PhysicalTopN {
p.basePhysicalPlan = newBasePhysicalPlan(ctx, TypeTopN, &p)
p.childrenReqProps = props
p.stats = stats
Expand All @@ -176,7 +176,7 @@ func (p LogicalLimit) init(ctx sessionctx.Context) *LogicalLimit {
return &p
}

func (p PhysicalLimit) init(ctx sessionctx.Context, stats *statsInfo, props ...*requiredProp) *PhysicalLimit {
func (p PhysicalLimit) init(ctx sessionctx.Context, stats *StatsInfo, props ...*requiredProp) *PhysicalLimit {
p.basePhysicalPlan = newBasePhysicalPlan(ctx, TypeLimit, &p)
p.childrenReqProps = props
p.stats = stats
Expand All @@ -188,7 +188,7 @@ func (p LogicalTableDual) init(ctx sessionctx.Context) *LogicalTableDual {
return &p
}

func (p PhysicalTableDual) init(ctx sessionctx.Context, stats *statsInfo) *PhysicalTableDual {
func (p PhysicalTableDual) init(ctx sessionctx.Context, stats *StatsInfo) *PhysicalTableDual {
p.basePhysicalPlan = newBasePhysicalPlan(ctx, TypeDual, &p)
p.stats = stats
return &p
Expand All @@ -199,7 +199,7 @@ func (p LogicalExists) init(ctx sessionctx.Context) *LogicalExists {
return &p
}

func (p PhysicalExists) init(ctx sessionctx.Context, stats *statsInfo, props ...*requiredProp) *PhysicalExists {
func (p PhysicalExists) init(ctx sessionctx.Context, stats *StatsInfo, props ...*requiredProp) *PhysicalExists {
p.basePhysicalPlan = newBasePhysicalPlan(ctx, TypeExists, &p)
p.childrenReqProps = props
p.stats = stats
Expand All @@ -211,7 +211,7 @@ func (p LogicalMaxOneRow) init(ctx sessionctx.Context) *LogicalMaxOneRow {
return &p
}

func (p PhysicalMaxOneRow) init(ctx sessionctx.Context, stats *statsInfo, props ...*requiredProp) *PhysicalMaxOneRow {
func (p PhysicalMaxOneRow) init(ctx sessionctx.Context, stats *StatsInfo, props ...*requiredProp) *PhysicalMaxOneRow {
p.basePhysicalPlan = newBasePhysicalPlan(ctx, TypeMaxOneRow, &p)
p.childrenReqProps = props
p.stats = stats
Expand Down Expand Up @@ -243,7 +243,7 @@ func (p LogicalLock) init(ctx sessionctx.Context) *LogicalLock {
return &p
}

func (p PhysicalLock) init(ctx sessionctx.Context, stats *statsInfo, props ...*requiredProp) *PhysicalLock {
func (p PhysicalLock) init(ctx sessionctx.Context, stats *StatsInfo, props ...*requiredProp) *PhysicalLock {
p.basePhysicalPlan = newBasePhysicalPlan(ctx, TypeLock, &p)
p.childrenReqProps = props
p.stats = stats
Expand All @@ -260,13 +260,13 @@ func (p PhysicalIndexScan) init(ctx sessionctx.Context) *PhysicalIndexScan {
return &p
}

func (p PhysicalMemTable) init(ctx sessionctx.Context, stats *statsInfo) *PhysicalMemTable {
func (p PhysicalMemTable) init(ctx sessionctx.Context, stats *StatsInfo) *PhysicalMemTable {
p.basePhysicalPlan = newBasePhysicalPlan(ctx, TypeMemTableScan, &p)
p.stats = stats
return &p
}

func (p PhysicalHashJoin) init(ctx sessionctx.Context, stats *statsInfo, props ...*requiredProp) *PhysicalHashJoin {
func (p PhysicalHashJoin) init(ctx sessionctx.Context, stats *StatsInfo, props ...*requiredProp) *PhysicalHashJoin {
tp := TypeHashRightJoin
if p.InnerChildIdx == 1 {
tp = TypeHashLeftJoin
Expand All @@ -277,42 +277,42 @@ func (p PhysicalHashJoin) init(ctx sessionctx.Context, stats *statsInfo, props .
return &p
}

func (p PhysicalMergeJoin) init(ctx sessionctx.Context, stats *statsInfo) *PhysicalMergeJoin {
func (p PhysicalMergeJoin) init(ctx sessionctx.Context, stats *StatsInfo) *PhysicalMergeJoin {
p.basePhysicalPlan = newBasePhysicalPlan(ctx, TypeMergeJoin, &p)
p.stats = stats
return &p
}

func (base basePhysicalAgg) init(ctx sessionctx.Context, stats *statsInfo) *basePhysicalAgg {
func (base basePhysicalAgg) init(ctx sessionctx.Context, stats *StatsInfo) *basePhysicalAgg {
base.basePhysicalPlan = newBasePhysicalPlan(ctx, TypeHashAgg, &base)
base.stats = stats
return &base
}

func (base basePhysicalAgg) initForHash(ctx sessionctx.Context, stats *statsInfo, props ...*requiredProp) *PhysicalHashAgg {
func (base basePhysicalAgg) initForHash(ctx sessionctx.Context, stats *StatsInfo, props ...*requiredProp) *PhysicalHashAgg {
p := &PhysicalHashAgg{base}
p.basePhysicalPlan = newBasePhysicalPlan(ctx, TypeHashAgg, p)
p.childrenReqProps = props
p.stats = stats
return p
}

func (base basePhysicalAgg) initForStream(ctx sessionctx.Context, stats *statsInfo, props ...*requiredProp) *PhysicalStreamAgg {
func (base basePhysicalAgg) initForStream(ctx sessionctx.Context, stats *StatsInfo, props ...*requiredProp) *PhysicalStreamAgg {
p := &PhysicalStreamAgg{base}
p.basePhysicalPlan = newBasePhysicalPlan(ctx, TypeStreamAgg, p)
p.childrenReqProps = props
p.stats = stats
return p
}

func (p PhysicalApply) init(ctx sessionctx.Context, stats *statsInfo, props ...*requiredProp) *PhysicalApply {
func (p PhysicalApply) init(ctx sessionctx.Context, stats *StatsInfo, props ...*requiredProp) *PhysicalApply {
p.basePhysicalPlan = newBasePhysicalPlan(ctx, TypeApply, &p)
p.childrenReqProps = props
p.stats = stats
return &p
}

func (p PhysicalUnionScan) init(ctx sessionctx.Context, stats *statsInfo, props ...*requiredProp) *PhysicalUnionScan {
func (p PhysicalUnionScan) init(ctx sessionctx.Context, stats *StatsInfo, props ...*requiredProp) *PhysicalUnionScan {
p.basePhysicalPlan = newBasePhysicalPlan(ctx, TypeUnionScan, &p)
p.childrenReqProps = props
p.stats = stats
Expand Down Expand Up @@ -348,7 +348,7 @@ func (p PhysicalIndexReader) init(ctx sessionctx.Context) *PhysicalIndexReader {
return &p
}

func (p PhysicalIndexJoin) init(ctx sessionctx.Context, stats *statsInfo, props ...*requiredProp) *PhysicalIndexJoin {
func (p PhysicalIndexJoin) init(ctx sessionctx.Context, stats *StatsInfo, props ...*requiredProp) *PhysicalIndexJoin {
p.basePhysicalPlan = newBasePhysicalPlan(ctx, TypeIndexJoin, &p)
p.childrenReqProps = props
p.stats = stats
Expand Down
4 changes: 2 additions & 2 deletions plan/logical_plans.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,8 +299,8 @@ type DataSource struct {
// relevantIndices means the indices match the push down conditions
relevantIndices []bool

// statsAfterSelect is the statsInfo for dataSource and selection.
statsAfterSelect *statsInfo
// statsAfterSelect is the StatsInfo for dataSource and selection.
statsAfterSelect *StatsInfo

statisticTable *statistics.Table

Expand Down
4 changes: 2 additions & 2 deletions plan/physical_plan_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ func (is *PhysicalIndexScan) addPushedDownSelection(copTask *copTask, p *DataSou
selectivity := path.countAfterIndex / path.countAfterAccess
count = is.stats.count * selectivity
}
stats := &statsInfo{count: count}
stats := &StatsInfo{count: count}
indexSel := PhysicalSelection{Conditions: indexConds}.init(is.ctx, stats)
indexSel.SetChildren(is)
copTask.indexPlan = indexSel
Expand Down Expand Up @@ -565,7 +565,7 @@ func (ds *DataSource) convertToTableScan(prop *requiredProp, path *accessPath) (
return task, nil
}

func (ts *PhysicalTableScan) addPushedDownSelection(copTask *copTask, stats *statsInfo) {
func (ts *PhysicalTableScan) addPushedDownSelection(copTask *copTask, stats *StatsInfo) {
// Add filter condition to table plan now.
if len(ts.filterCondition) > 0 {
copTask.cst += copTask.count() * cpuFactor
Expand Down
15 changes: 10 additions & 5 deletions plan/plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ type Plan interface {
replaceExprColumns(replace map[string]*expression.Column)

context() sessionctx.Context

// StatsInfo will return the StatsInfo for this plan.
StatsInfo() *StatsInfo
}

// taskType is the type of execution task.
Expand Down Expand Up @@ -161,7 +164,7 @@ type LogicalPlan interface {
pushDownTopN(topN *LogicalTopN) LogicalPlan

// deriveStats derives statistic info between plans.
deriveStats() (*statsInfo, error)
deriveStats() (*StatsInfo, error)

// preparePossibleProperties is only used for join and aggregation. Like group by a,b,c, all permutation of (a,b,c) is
// valid, but the ordered indices in leaf plan is limited. So we can get all possible order properties by a pre-walking.
Expand Down Expand Up @@ -205,9 +208,6 @@ type PhysicalPlan interface {
// getChildReqProps gets the required property by child index.
getChildReqProps(idx int) *requiredProp

// StatsInfo will return the statsInfo for this plan.
StatsInfo() *statsInfo

// Get all the children.
Children() []PhysicalPlan

Expand Down Expand Up @@ -270,6 +270,11 @@ func (p *baseLogicalPlan) buildKeyInfo() {
}
}

// StatsInfo implements the Plan.StatsInfo interface.
func (p *DataSource) StatsInfo() *StatsInfo {
return p.statsAfterSelect
}

func newBasePlan(ctx sessionctx.Context, tp string) basePlan {
ctx.GetSessionVars().PlanID++
id := ctx.GetSessionVars().PlanID
Expand Down Expand Up @@ -317,7 +322,7 @@ type basePlan struct {
tp string
id int
ctx sessionctx.Context
stats *statsInfo
stats *StatsInfo
}

func (p *basePlan) replaceExprColumns(replace map[string]*expression.Column) {
Expand Down
2 changes: 1 addition & 1 deletion plan/planbuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ func (b *planBuilder) buildCheckIndex(dbName model.CIStr, as *ast.AdminStmt) Pla
Ranges: ranger.FullNewRange(),
KeepOrder: false,
}.init(b.ctx)
is.stats = &statsInfo{}
is.stats = &StatsInfo{}
cop := &copTask{indexPlan: is}
// It's double read case.
ts := PhysicalTableScan{Columns: columns, Table: is.Table}.init(b.ctx)
Expand Down
Loading

0 comments on commit f7edb2b

Please sign in to comment.