Skip to content

Commit

Permalink
planner: use *expression.Column instead of *IndexColumn (#11894)
Browse files Browse the repository at this point in the history
  • Loading branch information
winoros authored Sep 5, 2019
1 parent c88ff80 commit e0b8267
Show file tree
Hide file tree
Showing 15 changed files with 194 additions and 141 deletions.
16 changes: 8 additions & 8 deletions cmd/explaintest/r/explain_complex.result
Original file line number Diff line number Diff line change
Expand Up @@ -245,17 +245,17 @@ id count task operator info
Sort_10 1.00 root test.d.left_value:asc
└─HashAgg_15 1.00 root group by:test.d.id, funcs:firstrow(test.d.id), firstrow(test.d.ctx), firstrow(test.d.name), firstrow(test.d.left_value), firstrow(test.d.right_value), firstrow(test.d.depth), firstrow(test.d.leader_id), firstrow(test.d.status), firstrow(test.d.created_on), firstrow(test.d.updated_on)
└─Selection_22 0.01 root or(eq(test.ep.user_id, 62), or(eq(test.d.id, 20), eq(test.d.id, 20)))
└─HashLeftJoin_23 0.02 root left outer join, inner:TableReader_64, equal:[eq(test.p.id, test.ep.position_id)]
└─HashLeftJoin_23 0.02 root left outer join, inner:TableReader_68, equal:[eq(test.p.id, test.ep.position_id)]
├─IndexMergeJoin_39 0.01 root left outer join, inner:IndexLookUp_37, outer key:test.d.id, inner key:test.p.department_id
│ ├─IndexLookUp_54 0.01 root
│ │ ├─IndexScan_51 10.00 cop table:d, index:ctx, range:[1,1], keep order:false, stats:pseudo
│ │ └─Selection_53 0.01 cop eq(test.d.status, 1000)
│ │ └─TableScan_52 10.00 cop table:d, keep order:false, stats:pseudo
│ ├─IndexLookUp_58 0.01 root
│ │ ├─IndexScan_55 10.00 cop table:d, index:ctx, range:[1,1], keep order:false, stats:pseudo
│ │ └─Selection_57 0.01 cop eq(test.d.status, 1000)
│ │ └─TableScan_56 10.00 cop table:d, keep order:false, stats:pseudo
│ └─IndexLookUp_37 0.01 root
│ ├─Selection_35 9.99 cop not(isnull(test.p.department_id))
│ │ └─IndexScan_33 10.00 cop table:p, index:department_id, range: decided by [eq(test.p.department_id, test.d.id)], keep order:true, stats:pseudo
│ └─Selection_36 0.01 cop eq(test.p.status, 1000)
│ └─TableScan_34 9.99 cop table:p, keep order:false, stats:pseudo
└─TableReader_64 9.99 root data:Selection_63
└─Selection_63 9.99 cop eq(test.ep.status, 1000), not(isnull(test.ep.position_id))
└─TableScan_62 10000.00 cop table:ep, range:[-inf,+inf], keep order:false, stats:pseudo
└─TableReader_68 9.99 root data:Selection_67
└─Selection_67 9.99 cop eq(test.ep.status, 1000), not(isnull(test.ep.position_id))
└─TableScan_66 10000.00 cop table:ep, range:[-inf,+inf], keep order:false, stats:pseudo
26 changes: 13 additions & 13 deletions cmd/explaintest/r/explain_easy.result
Original file line number Diff line number Diff line change
Expand Up @@ -356,13 +356,13 @@ Projection_11 5.00 root 9_aux_0
├─TableReader_15 5.00 root data:TableScan_14
│ └─TableScan_14 5.00 cop table:t, range:[-inf,+inf], keep order:false
└─StreamAgg_20 1.00 root funcs:count(1)
└─IndexMergeJoin_65 2.40 root inner join, inner:TableReader_63, outer key:test.s.a, inner key:test.t1.a
├─IndexReader_51 2.40 root index:Selection_50
│ └─Selection_50 2.40 cop eq(3, test.t.a)
│ └─IndexScan_49 3.00 cop table:s, index:b, range:[3,3], keep order:false
└─TableReader_63 0.80 root data:Selection_62
└─Selection_62 0.80 cop eq(3, test.t.a)
└─TableScan_61 1.00 cop table:t1, range: decided by [test.s.a], keep order:true
└─MergeJoin_55 2.40 root inner join, left key:test.s.a, right key:test.t1.a
├─IndexReader_45 2.40 root index:Selection_44
│ └─Selection_44 2.40 cop eq(3, test.t.a)
│ └─IndexScan_43 3.00 cop table:s, index:b, range:[3,3], keep order:true
└─TableReader_48 4.00 root data:Selection_47
└─Selection_47 4.00 cop eq(3, test.t.a)
└─TableScan_46 5.00 cop table:t1, range:[-inf,+inf], keep order:true
explain select t.c in (select count(*) from t s left join t t1 on s.a = t1.a where 3 = t.a and s.b = 3) from t;
id count task operator info
Projection_10 5.00 root 9_aux_0
Expand All @@ -371,9 +371,9 @@ Projection_10 5.00 root 9_aux_0
│ └─TableScan_13 5.00 cop table:t, range:[-inf,+inf], keep order:false
└─StreamAgg_19 1.00 root funcs:count(1)
└─MergeJoin_44 2.40 root left outer join, left key:test.s.a, right key:test.t1.a
├─TableReader_34 2.40 root data:Selection_33
│ └─Selection_33 2.40 cop eq(3, test.t.a), eq(test.s.b, 3)
│ └─TableScan_32 5.00 cop table:s, range:[-inf,+inf], keep order:true
├─IndexReader_34 2.40 root index:Selection_33
│ └─Selection_33 2.40 cop eq(3, test.t.a)
│ └─IndexScan_32 3.00 cop table:s, index:b, range:[3,3], keep order:true
└─TableReader_37 4.00 root data:Selection_36
└─Selection_36 4.00 cop eq(3, test.t.a)
└─TableScan_35 5.00 cop table:t1, range:[-inf,+inf], keep order:true
Expand All @@ -388,9 +388,9 @@ Projection_10 5.00 root 9_aux_0
├─TableReader_33 4.00 root data:Selection_32
│ └─Selection_32 4.00 cop eq(3, test.t.a)
│ └─TableScan_31 5.00 cop table:s, range:[-inf,+inf], keep order:true
└─TableReader_36 2.40 root data:Selection_35
└─Selection_35 2.40 cop eq(3, test.t.a), eq(test.t1.b, 3)
└─TableScan_34 5.00 cop table:t1, range:[-inf,+inf], keep order:true
└─IndexReader_36 2.40 root index:Selection_35
└─Selection_35 2.40 cop eq(3, test.t.a)
└─IndexScan_34 3.00 cop table:t1, index:b, range:[3,3], keep order:true
drop table if exists t;
create table t(a int unsigned);
explain select t.a = '123455' from t;
Expand Down
29 changes: 27 additions & 2 deletions expression/column.go
Original file line number Diff line number Diff line change
Expand Up @@ -497,11 +497,12 @@ func indexCol2Col(cols []*Column, col *model.IndexColumn) *Column {
return nil
}

// IndexInfo2Cols gets the corresponding []*Column of the indexInfo's []*IndexColumn,
// IndexInfo2PrefixCols gets the corresponding []*Column of the indexInfo's []*IndexColumn,
// together with a []int containing their lengths.
// 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 and its length.
func IndexInfo2Cols(cols []*Column, index *model.IndexInfo) ([]*Column, []int) {
// TODO: Use a struct to represent {*Column, int}. And merge IndexInfo2PrefixCols and IndexInfo2Cols.
func IndexInfo2PrefixCols(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 {
Expand All @@ -519,6 +520,30 @@ func IndexInfo2Cols(cols []*Column, index *model.IndexInfo) ([]*Column, []int) {
return retCols, lengths
}

// IndexInfo2Cols gets the corresponding []*Column of the indexInfo's []*IndexColumn,
// together with a []int containing their lengths.
// If this index has three IndexColumn that the 1st and 3rd IndexColumn has corresponding *Column,
// the return value will be [col1, nil, col2].
func IndexInfo2Cols(cols []*Column, index *model.IndexInfo) ([]*Column, []int) {
retCols := make([]*Column, 0, len(index.Columns))
lens := make([]int, 0, len(index.Columns))
for _, c := range index.Columns {
col := indexCol2Col(cols, c)
if col == nil {
retCols = append(retCols, col)
lens = append(lens, types.UnspecifiedLength)
continue
}
retCols = append(retCols, col)
if c.Length != types.UnspecifiedLength && c.Length == col.RetType.Flen {
lens = append(lens, types.UnspecifiedLength)
} else {
lens = append(lens, c.Length)
}
}
return retCols, lens
}

// FindPrefixOfIndex will find columns in index by checking the unique id.
// So it will return at once no matching column is found.
func FindPrefixOfIndex(cols []*Column, idxColIDs []int64) []*Column {
Expand Down
6 changes: 3 additions & 3 deletions expression/column_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,18 +148,18 @@ func (s *testEvaluatorSuite) TestIndexInfo2Cols(c *C) {
indexInfo := &model.IndexInfo{Columns: []*model.IndexColumn{indexCol0, indexCol1}}

cols := []*Column{col0}
resCols, lengths := IndexInfo2Cols(cols, indexInfo)
resCols, lengths := IndexInfo2PrefixCols(cols, indexInfo)
c.Assert(len(resCols), Equals, 1)
c.Assert(len(lengths), Equals, 1)
c.Assert(resCols[0].Equal(nil, col0), IsTrue)

cols = []*Column{col1}
resCols, lengths = IndexInfo2Cols(cols, indexInfo)
resCols, lengths = IndexInfo2PrefixCols(cols, indexInfo)
c.Assert(len(resCols), Equals, 0)
c.Assert(len(lengths), Equals, 0)

cols = []*Column{col0, col1}
resCols, lengths = IndexInfo2Cols(cols, indexInfo)
resCols, lengths = IndexInfo2PrefixCols(cols, indexInfo)
c.Assert(len(resCols), Equals, 2)
c.Assert(len(lengths), Equals, 2)
c.Assert(resCols[0].Equal(nil, col0), IsTrue)
Expand Down
35 changes: 18 additions & 17 deletions planner/core/cbo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ func (s *testAnalyzeSuite) TestIndexRead(c *C) {
},
{
sql: "select * from t use index(b) where b = 1 order by a",
best: "IndexLookUp(Index(t.b)[[1,1]], Table(t))->Sort",
best: "IndexLookUp(Index(t.b)[[1,1]], Table(t))",
},
// test datetime
{
Expand Down Expand Up @@ -996,33 +996,33 @@ func (s *testAnalyzeSuite) TestLimitCrossEstimation(c *C) {

tk.MustExec("use test")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t(a int primary key, b int not null, index idx_b(b))")
tk.MustExec("create table t(a int primary key, b int not null, c int not null default 0, index idx_bc(b, c))")
tk.MustExec("set session tidb_opt_correlation_exp_factor = 0")
// Pseudo stats.
tk.MustQuery("EXPLAIN SELECT * FROM t WHERE b = 2 ORDER BY a limit 1;").Check(testkit.Rows(
"TopN_8 1.00 root test.t.a:asc, offset:0, count:1",
"└─IndexReader_16 1.00 root index:TopN_15",
" └─TopN_15 1.00 cop test.t.a:asc, offset:0, count:1",
" └─IndexScan_14 10.00 cop table:t, index:b, range:[2,2], keep order:false, stats:pseudo",
" └─IndexScan_14 10.00 cop table:t, index:b, c, range:[2,2], keep order:false, stats:pseudo",
))
// Positive correlation.
tk.MustExec("insert into t values (1, 1),(2, 1),(3, 1),(4, 1),(5, 1),(6, 1),(7, 1),(8, 1),(9, 1),(10, 1),(11, 1),(12, 1),(13, 1),(14, 1),(15, 1),(16, 1),(17, 1),(18, 1),(19, 1),(20, 2),(21, 2),(22, 2),(23, 2),(24, 2),(25, 2)")
tk.MustExec("insert into t (a, b) values (1, 1),(2, 1),(3, 1),(4, 1),(5, 1),(6, 1),(7, 1),(8, 1),(9, 1),(10, 1),(11, 1),(12, 1),(13, 1),(14, 1),(15, 1),(16, 1),(17, 1),(18, 1),(19, 1),(20, 2),(21, 2),(22, 2),(23, 2),(24, 2),(25, 2)")
tk.MustExec("analyze table t")
tk.MustQuery("EXPLAIN SELECT * FROM t WHERE b = 2 ORDER BY a limit 1;").Check(testkit.Rows(
"TopN_8 1.00 root test.t.a:asc, offset:0, count:1",
"└─IndexReader_16 1.00 root index:TopN_15",
" └─TopN_15 1.00 cop test.t.a:asc, offset:0, count:1",
" └─IndexScan_14 6.00 cop table:t, index:b, range:[2,2], keep order:false",
" └─IndexScan_14 6.00 cop table:t, index:b, c, range:[2,2], keep order:false",
))
// Negative correlation.
tk.MustExec("truncate table t")
tk.MustExec("insert into t values (1, 25),(2, 24),(3, 23),(4, 23),(5, 21),(6, 20),(7, 19),(8, 18),(9, 17),(10, 16),(11, 15),(12, 14),(13, 13),(14, 12),(15, 11),(16, 10),(17, 9),(18, 8),(19, 7),(20, 6),(21, 5),(22, 4),(23, 3),(24, 2),(25, 1)")
tk.MustExec("insert into t (a, b) values (1, 25),(2, 24),(3, 23),(4, 23),(5, 21),(6, 20),(7, 19),(8, 18),(9, 17),(10, 16),(11, 15),(12, 14),(13, 13),(14, 12),(15, 11),(16, 10),(17, 9),(18, 8),(19, 7),(20, 6),(21, 5),(22, 4),(23, 3),(24, 2),(25, 1)")
tk.MustExec("analyze table t")
tk.MustQuery("EXPLAIN SELECT * FROM t WHERE b <= 6 ORDER BY a limit 1").Check(testkit.Rows(
"TopN_8 1.00 root test.t.a:asc, offset:0, count:1",
"└─IndexReader_16 1.00 root index:TopN_15",
" └─TopN_15 1.00 cop test.t.a:asc, offset:0, count:1",
" └─IndexScan_14 6.00 cop table:t, index:b, range:[-inf,6], keep order:false",
" └─IndexScan_14 6.00 cop table:t, index:b, c, range:[-inf,6], keep order:false",
))
// Outer plan of index join (to test that correct column ID is used).
tk.MustQuery("EXPLAIN SELECT *, t1.a IN (SELECT t2.b FROM t t2) FROM t t1 WHERE t1.b <= 6 ORDER BY t1.a limit 1").Check(testkit.Rows(
Expand All @@ -1031,23 +1031,23 @@ func (s *testAnalyzeSuite) TestLimitCrossEstimation(c *C) {
" ├─TopN_27 1.00 root test.t1.a:asc, offset:0, count:1",
" │ └─IndexReader_35 1.00 root index:TopN_34",
" │ └─TopN_34 1.00 cop test.t1.a:asc, offset:0, count:1",
" │ └─IndexScan_33 6.00 cop table:t1, index:b, range:[-inf,6], keep order:false",
" │ └─IndexScan_33 6.00 cop table:t1, index:b, c, range:[-inf,6], keep order:false",
" └─IndexReader_64 1.04 root index:IndexScan_63",
" └─IndexScan_63 1.04 cop table:t2, index:b, range: decided by [eq(test.t2.b, test.t1.a)], keep order:true",
" └─IndexScan_63 1.04 cop table:t2, index:b, c, range: decided by [eq(test.t2.b, test.t1.a)], keep order:true",
))
// Desc TableScan.
tk.MustExec("truncate table t")
tk.MustExec("insert into t values (1, 1),(2, 1),(3, 1),(4, 1),(5, 1),(6, 1),(7, 2),(8, 2),(9, 2),(10, 2),(11, 2),(12, 2),(13, 2),(14, 2),(15, 2),(16, 2),(17, 2),(18, 2),(19, 2),(20, 2),(21, 2),(22, 2),(23, 2),(24, 2),(25, 2)")
tk.MustExec("insert into t (a, b) values (1, 1),(2, 1),(3, 1),(4, 1),(5, 1),(6, 1),(7, 2),(8, 2),(9, 2),(10, 2),(11, 2),(12, 2),(13, 2),(14, 2),(15, 2),(16, 2),(17, 2),(18, 2),(19, 2),(20, 2),(21, 2),(22, 2),(23, 2),(24, 2),(25, 2)")
tk.MustExec("analyze table t")
tk.MustQuery("EXPLAIN SELECT * FROM t WHERE b = 1 ORDER BY a desc limit 1").Check(testkit.Rows(
"TopN_8 1.00 root test.t.a:desc, offset:0, count:1",
"└─IndexReader_16 1.00 root index:TopN_15",
" └─TopN_15 1.00 cop test.t.a:desc, offset:0, count:1",
" └─IndexScan_14 6.00 cop table:t, index:b, range:[1,1], keep order:false",
" └─IndexScan_14 6.00 cop table:t, index:b, c, range:[1,1], keep order:false",
))
// Correlation threshold not met.
tk.MustExec("truncate table t")
tk.MustExec("insert into t values (1, 1),(2, 1),(3, 1),(4, 1),(5, 1),(6, 1),(7, 1),(8, 1),(9, 2),(10, 1),(11, 1),(12, 1),(13, 1),(14, 2),(15, 2),(16, 1),(17, 2),(18, 1),(19, 2),(20, 1),(21, 2),(22, 1),(23, 1),(24, 1),(25, 1)")
tk.MustExec("insert into t (a, b) values (1, 1),(2, 1),(3, 1),(4, 1),(5, 1),(6, 1),(7, 1),(8, 1),(9, 2),(10, 1),(11, 1),(12, 1),(13, 1),(14, 2),(15, 2),(16, 1),(17, 2),(18, 1),(19, 2),(20, 1),(21, 2),(22, 1),(23, 1),(24, 1),(25, 1)")
tk.MustExec("analyze table t")
tk.MustQuery("EXPLAIN SELECT * FROM t WHERE b = 2 ORDER BY a limit 1").Check(testkit.Rows(
"Limit_11 1.00 root offset:0, count:1",
Expand All @@ -1061,18 +1061,19 @@ func (s *testAnalyzeSuite) TestLimitCrossEstimation(c *C) {
"TopN_8 1.00 root test.t.a:asc, offset:0, count:1",
"└─IndexReader_16 1.00 root index:TopN_15",
" └─TopN_15 1.00 cop test.t.a:asc, offset:0, count:1",
" └─IndexScan_14 6.00 cop table:t, index:b, range:[2,2], keep order:false",
" └─IndexScan_14 6.00 cop table:t, index:b, c, range:[2,2], keep order:false",
))
tk.MustExec("set session tidb_opt_correlation_exp_factor = 0")
// TableScan has access conditions, but correlation is 1.
tk.MustExec("truncate table t")
tk.MustExec("insert into t values (1, 1),(2, 1),(3, 1),(4, 1),(5, 1),(6, 1),(7, 1),(8, 1),(9, 1),(10, 1),(11, 1),(12, 1),(13, 1),(14, 1),(15, 1),(16, 1),(17, 1),(18, 1),(19, 1),(20, 2),(21, 2),(22, 2),(23, 2),(24, 2),(25, 2)")
tk.MustExec("insert into t (a, b) values (1, 1),(2, 1),(3, 1),(4, 1),(5, 1),(6, 1),(7, 1),(8, 1),(9, 1),(10, 1),(11, 1),(12, 1),(13, 1),(14, 1),(15, 1),(16, 1),(17, 1),(18, 1),(19, 1),(20, 2),(21, 2),(22, 2),(23, 2),(24, 2),(25, 2)")
tk.MustExec("analyze table t")
tk.MustQuery("EXPLAIN SELECT * FROM t WHERE b = 2 and a > 0 ORDER BY a limit 1").Check(testkit.Rows(
"TopN_8 1.00 root test.t.a:asc, offset:0, count:1",
"└─IndexReader_16 1.00 root index:TopN_15",
" └─TopN_15 1.00 cop test.t.a:asc, offset:0, count:1",
" └─IndexScan_14 7.50 cop table:t, index:b, range:(2 0,2 +inf], keep order:false",
"└─IndexReader_19 1.00 root index:TopN_18",
" └─TopN_18 1.00 cop test.t.a:asc, offset:0, count:1",
" └─Selection_17 6.00 cop gt(test.t.a, 0)",
" └─IndexScan_16 6.00 cop table:t, index:b, c, range:[2,2], keep order:false",
))
// Multi-column filter.
tk.MustExec("drop table t")
Expand Down
2 changes: 1 addition & 1 deletion planner/core/common_plans.go
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ func (e *Execute) rebuildRange(p Plan) error {
}

func (e *Execute) buildRangeForIndexScan(sctx sessionctx.Context, is *PhysicalIndexScan) ([]*ranger.Range, error) {
idxCols, colLengths := expression.IndexInfo2Cols(is.schema.Columns, is.Index)
idxCols, colLengths := expression.IndexInfo2PrefixCols(is.schema.Columns, is.Index)
if len(idxCols) == 0 {
return ranger.FullRange(), nil
}
Expand Down
Loading

0 comments on commit e0b8267

Please sign in to comment.