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

ranger: add a more common method to calc range. #3489

Merged
merged 19 commits into from
Jun 21, 2017
Merged
37 changes: 37 additions & 0 deletions expression/column.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,3 +245,40 @@ func Column2Exprs(cols []*Column) []Expression {
}
return result
}

// ColInfo2Col finds the corresponding column of the ColumnInfo in a column slice.
func ColInfo2Col(cols []*Column, col *model.ColumnInfo) *Column {
for _, c := range cols {
if c.ColName.L == col.Name.L {
return c
}
}
return nil
}

// indexCol2Col finds the corresponding column of the IndexColumn in a column slice.
func indexCol2Col(cols []*Column, col *model.IndexColumn) *Column {
for _, c := range cols {
if c.ColName.L == col.Name.L {
return c
}
}
return nil
}

// IndexInfo2Cols changes a indexInfo's []*IndexColumn to corresponding []*Column and the length of each *IndexColumn.
Copy link
Member

Choose a reason for hiding this comment

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

The first sentence is not clear.

// If this index has three IndexColumn that the 1st and 3rd IndexColumn has corresponding *Column,
// the return value will be only the 1st corresponding *Column.
func IndexInfo2Cols(cols []*Column, index *model.IndexInfo) ([]*Column, []int) {
retCols := make([]*Column, 0, len(index.Columns))
lengths := make([]int, 0, len(index.Columns))
for _, c := range index.Columns {
col := indexCol2Col(cols, c)
if col == nil {
return retCols, lengths
}
retCols = append(retCols, col)
lengths = append(lengths, c.Length)
}
return retCols, lengths
}
12 changes: 12 additions & 0 deletions model/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,18 @@ func (t *TableInfo) GetPkName() CIStr {
return CIStr{}
}

// GetPkColInfo gets the ColumnInfo of pk if exists.
func (t *TableInfo) GetPkColInfo() *ColumnInfo {
if t.PKIsHandle {
Copy link
Member

Choose a reason for hiding this comment

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

This check can be removed

for _, colInfo := range t.Columns {
if mysql.HasPriKeyFlag(colInfo.Flag) {
return colInfo
}
}
}
return nil
}

// IndexColumn provides index column info.
type IndexColumn struct {
Name CIStr `json:"name"` // Index name
Expand Down
67 changes: 36 additions & 31 deletions plan/new_physical_plan_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"math"

"github.com/juju/errors"
"github.com/pingcap/tidb/ast"
"github.com/pingcap/tidb/context"
"github.com/pingcap/tidb/expression"
"github.com/pingcap/tidb/infoschema"
Expand Down Expand Up @@ -685,23 +686,28 @@ func (p *DataSource) convertToIndexScan(prop *requiredProp, idx *model.IndexInfo
statsTbl := p.statisticTable
rowCount := float64(statsTbl.Count)
sc := p.ctx.GetSessionVars().StmtCtx
idxCols, colLengths := expression.IndexInfo2Cols(p.Schema().Columns, idx)
rb := ranger.Builder{Sc: sc}
is.Ranges = rb.BuildIndexRanges(ranger.FullRange, types.NewFieldType(mysql.TypeNull))
if len(p.pushedDownConds) > 0 {
conds := make([]expression.Expression, 0, len(p.pushedDownConds))
for _, cond := range p.pushedDownConds {
conds = append(conds, cond.Clone())
}
is.AccessCondition, is.filterCondition, is.accessEqualCount, is.accessInAndEqCount = ranger.DetachIndexScanConditions(conds, idx)
is.Ranges, err = ranger.BuildIndexRange(sc, is.Table, is.Index, is.accessInAndEqCount, is.AccessCondition)
if err != nil {
return nil, errors.Trace(err)
}
rowCount, err = statsTbl.GetRowCountByIndexRanges(sc, is.Index.ID, is.Ranges, is.accessInAndEqCount)
if err != nil {
return nil, errors.Trace(err)
if len(idxCols) > 0 {
var ranges []types.Range
ranges, is.AccessCondition, is.filterCondition, err = ranger.BuildRange(sc, conds, ranger.IndexRangeType, idxCols, colLengths)
if err != nil {
return nil, errors.Trace(err)
}
is.Ranges = ranger.RangeSlice2IndexRangeSlice(ranges)
rowCount, err = statsTbl.GetRowCountByIndexRanges(sc, is.Index.ID, is.Ranges, len(is.AccessCondition))
if err != nil {
return nil, errors.Trace(err)
}
} else {
is.filterCondition = conds
}
} else {
rb := ranger.Builder{Sc: sc}
is.Ranges = rb.BuildIndexRanges(ranger.FullRange, types.NewFieldType(mysql.TypeNull))
}
cop := &copTask{
cnt: rowCount,
Expand Down Expand Up @@ -741,7 +747,7 @@ func (p *DataSource) convertToIndexScan(prop *requiredProp, idx *model.IndexInfo
if col.Name.L == prop.cols[0].ColName.L {
matchProperty = matchIndicesProp(idx.Columns[i:], prop.cols)
break
} else if i >= is.accessEqualCount {
} else if i >= len(is.AccessCondition) || is.AccessCondition[i].(*expression.ScalarFunction).FuncName.L != ast.EQ {
matchProperty = false
break
}
Expand Down Expand Up @@ -820,34 +826,33 @@ func (p *DataSource) convertToTableScan(prop *requiredProp) (task task, err erro
}.init(p.allocator, p.ctx)
ts.SetSchema(p.schema)
sc := p.ctx.GetSessionVars().StmtCtx
ts.Ranges = []types.IntColumnRange{{math.MinInt64, math.MaxInt64}}
var pkCol *expression.Column
if pkColInfo := ts.Table.GetPkColInfo(); pkColInfo != nil {
pkCol = expression.ColInfo2Col(ts.schema.Columns, pkColInfo)
}
if len(p.pushedDownConds) > 0 {
conds := make([]expression.Expression, 0, len(p.pushedDownConds))
for _, cond := range p.pushedDownConds {
conds = append(conds, cond.Clone())
}
ts.AccessCondition, ts.filterCondition = ranger.DetachColumnConditions(conds, p.tableInfo.GetPkName())
ts.Ranges, err = ranger.BuildTableRange(ts.AccessCondition, sc)
if err != nil {
return nil, errors.Trace(err)
}
} else {
ts.Ranges = []types.IntColumnRange{{math.MinInt64, math.MaxInt64}}
}
statsTbl := p.statisticTable
rowCount := float64(statsTbl.Count)
var pkCol *expression.Column
if p.tableInfo.PKIsHandle {
for i, colInfo := range ts.Columns {
if mysql.HasPriKeyFlag(colInfo.Flag) {
pkCol = p.Schema().Columns[i]
break
}
}
if pkCol != nil {
rowCount, err = statsTbl.GetRowCountByIntColumnRanges(sc, pkCol.ID, ts.Ranges)
var ranges []types.Range
ranges, ts.AccessCondition, ts.filterCondition, err = ranger.BuildRange(sc, conds, ranger.IntRangeType, []*expression.Column{pkCol}, nil)
ts.Ranges = ranger.RangeSlice2IntRangeSlice(ranges)
if err != nil {
return nil, errors.Trace(err)
}
} else {
ts.filterCondition = conds
}
}
statsTbl := p.statisticTable
rowCount := float64(statsTbl.Count)
if pkCol != nil {
rowCount, err = statsTbl.GetRowCountByIntColumnRanges(sc, pkCol.ID, ts.Ranges)
if err != nil {
return nil, errors.Trace(err)
}
}
cost := rowCount * scanFactor
Expand Down
3 changes: 1 addition & 2 deletions statistics/statistics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@
package statistics

import (
"testing"

. "github.com/pingcap/check"
"github.com/pingcap/tidb/ast"
"github.com/pingcap/tidb/model"
Expand All @@ -24,6 +22,7 @@ import (
"github.com/pingcap/tidb/util/codec"
"github.com/pingcap/tidb/util/mock"
"github.com/pingcap/tidb/util/types"
"testing"
)

func TestT(t *testing.T) {
Expand Down
Loading