Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 20 additions & 4 deletions pkg/planner/core/indexmerge_path.go
Original file line number Diff line number Diff line change
Expand Up @@ -1052,7 +1052,7 @@ func collectFilters4MVIndex(
usedAsAccess[i] = true
found = true
// access filter type on mv col overrides normal col for the return value of this function
if accessTp == unspecifiedFilterTp || accessTp == eqOnNonMVColTp {
if accessTp == unspecifiedFilterTp || accessTp == eqOrInOnNonMVColTp {
accessTp = tp
}
break
Expand Down Expand Up @@ -1207,7 +1207,7 @@ func indexMergeContainSpecificIndex(path *util.AccessPath, indexSet map[int64]st

const (
unspecifiedFilterTp int = iota
eqOnNonMVColTp
eqOrInOnNonMVColTp
multiValuesOROnMVColTp
multiValuesANDOnMVColTp
singleValueOnMVColTp
Expand Down Expand Up @@ -1301,7 +1301,23 @@ func checkAccessFilter4IdxCol(
}

// else: non virtual column
if sf.FuncName.L != ast.EQ { // only support EQ now
if sf.FuncName.L == ast.In {
args := sf.GetArgs()
if len(args) < 2 {
return false, unspecifiedFilterTp
}
c, isCol := args[0].(*expression.Column)
if !isCol || !c.Equal(sctx.GetExprCtx().GetEvalCtx(), idxCol) {
return false, unspecifiedFilterTp
}
for _, arg := range args[1:] {
if _, isCon := arg.(*expression.Constant); !isCon {
return false, unspecifiedFilterTp
}
}
Comment thread
winoros marked this conversation as resolved.
return true, eqOrInOnNonMVColTp
}
if sf.FuncName.L != ast.EQ {
return false, unspecifiedFilterTp
}
args := sf.GetArgs()
Expand All @@ -1320,7 +1336,7 @@ func checkAccessFilter4IdxCol(
return false, unspecifiedFilterTp
}
if argCol.Equal(sctx.GetExprCtx().GetEvalCtx(), idxCol) {
return true, eqOnNonMVColTp
return true, eqOrInOnNonMVColTp
}
return false, unspecifiedFilterTp
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/planner/core/indexmerge_unfinished_path.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ func initUnfinishedPathsFromExpr(
if ok, tp := checkAccessFilter4IdxCol(ds.SCtx(), cnfItem, col); ok &&
// Since we only handle the OR list nested in the AND list, and only generate IndexMerge OR path,
// we disable the multiValuesANDOnMVColTp case here.
(tp == eqOnNonMVColTp || tp == multiValuesOROnMVColTp || tp == singleValueOnMVColTp) {
(tp == eqOrInOnNonMVColTp || tp == multiValuesOROnMVColTp || tp == singleValueOnMVColTp) {
ret[i].usableFilters = append(ret[i].usableFilters, cnfItem)
ret[i].idxColHasUsableFilter[j] = true
// Once we find one valid access filter for this column, we directly go to the next column without
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3783,8 +3783,8 @@ id task access object operator info
Limit root offset:0, count:2
└─Projection root planner__core__casetest__physicalplantest__physical_plan.t.a, planner__core__casetest__physicalplantest__physical_plan.t.b, planner__core__casetest__physicalplantest__physical_plan.t.c
└─IndexMerge root type: union
├─IndexRangeScan(Build) cop[tikv] table:t, index:idx(a, c) range:[1,1], keep order:true, stats:pseudo
├─IndexRangeScan(Build) cop[tikv] table:t, index:idx2(b, c) range:[2,2], keep order:true, stats:pseudo
├─IndexRangeScan(Build) cop[tikv] table:t, index:idx(a, c) range:[1 1,1 1], [1 2,1 2], [1 3,1 3], keep order:true, stats:pseudo
├─IndexRangeScan(Build) cop[tikv] table:t, index:idx2(b, c) range:[2 1,2 1], [2 2,2 2], [2 3,2 3], keep order:true, stats:pseudo
└─Selection(Probe) cop[tikv] in(planner__core__casetest__physicalplantest__physical_plan.t.c, 1, 2, 3)
└─TableRowIDScan cop[tikv] table:t keep order:false, stats:pseudo
show warnings;
Expand All @@ -3793,8 +3793,8 @@ explain format = 'plan_tree' select * from t where (a = 1 or b = 2) and c in (1,
id task access object operator info
TopN root planner__core__casetest__physicalplantest__physical_plan.t.b, offset:0, count:2
└─IndexMerge root type: union
├─IndexRangeScan(Build) cop[tikv] table:t, index:idx(a, c) range:[1,1], keep order:false, stats:pseudo
├─IndexRangeScan(Build) cop[tikv] table:t, index:idx2(b, c) range:[2,2], keep order:false, stats:pseudo
├─IndexRangeScan(Build) cop[tikv] table:t, index:idx(a, c) range:[1 1,1 1], [1 2,1 2], [1 3,1 3], keep order:false, stats:pseudo
├─IndexRangeScan(Build) cop[tikv] table:t, index:idx2(b, c) range:[2 1,2 1], [2 2,2 2], [2 3,2 3], keep order:false, stats:pseudo
└─TopN(Probe) cop[tikv] planner__core__casetest__physicalplantest__physical_plan.t.b, offset:0, count:2
└─Selection cop[tikv] in(planner__core__casetest__physicalplantest__physical_plan.t.c, 1, 2, 3)
└─TableRowIDScan cop[tikv] table:t keep order:false, stats:pseudo
Expand Down
20 changes: 20 additions & 0 deletions tests/integrationtest/r/planner/core/indexmerge_path.result
Original file line number Diff line number Diff line change
Expand Up @@ -1373,3 +1373,23 @@ a b c
6 6 10
7 7 20
8 8 30
drop table if exists t1;
create table t1(a int, b int, c int, d int, e int, index iea(e,a), index ieb(e,b), index iec(e,c), index ied(e,d));
explain format = 'plan_tree' select /*+ use_index_merge(t1) */ * from t1 where e = 1 and (a in (1,2,3) or b in (2,3,4) or c in (3,4,5));
id task access object operator info
IndexMerge root type: union
├─IndexRangeScan(Build) cop[tikv] table:t1, index:iea(e, a) range:[1 1,1 1], [1 2,1 2], [1 3,1 3], keep order:false, stats:pseudo
├─IndexRangeScan(Build) cop[tikv] table:t1, index:ieb(e, b) range:[1 2,1 2], [1 3,1 3], [1 4,1 4], keep order:false, stats:pseudo
├─IndexRangeScan(Build) cop[tikv] table:t1, index:iec(e, c) range:[1 3,1 3], [1 4,1 4], [1 5,1 5], keep order:false, stats:pseudo
└─Selection(Probe) cop[tikv] eq(planner__core__indexmerge_path.t1.e, 1), or(in(planner__core__indexmerge_path.t1.a, 1, 2, 3), or(in(planner__core__indexmerge_path.t1.b, 2, 3, 4), in(planner__core__indexmerge_path.t1.c, 3, 4, 5)))
└─TableRowIDScan cop[tikv] table:t1 keep order:false, stats:pseudo
explain format = 'plan_tree' select /*+ use_index_merge(t1) */ * from t1 where e = 1 and (a in (1,2,3) or b in (2,3,4) or c in (3,4,5)) limit 3;
id task access object operator info
Limit root offset:0, count:3
└─IndexMerge root type: union
├─IndexRangeScan(Build) cop[tikv] table:t1, index:iea(e, a) range:[1 1,1 1], [1 2,1 2], [1 3,1 3], keep order:false, stats:pseudo
├─IndexRangeScan(Build) cop[tikv] table:t1, index:ieb(e, b) range:[1 2,1 2], [1 3,1 3], [1 4,1 4], keep order:false, stats:pseudo
├─IndexRangeScan(Build) cop[tikv] table:t1, index:iec(e, c) range:[1 3,1 3], [1 4,1 4], [1 5,1 5], keep order:false, stats:pseudo
└─Limit(Probe) cop[tikv] offset:0, count:3
└─Selection cop[tikv] eq(planner__core__indexmerge_path.t1.e, 1), or(in(planner__core__indexmerge_path.t1.a, 1, 2, 3), or(in(planner__core__indexmerge_path.t1.b, 2, 3, 4), in(planner__core__indexmerge_path.t1.c, 3, 4, 5)))
└─TableRowIDScan cop[tikv] table:t1 keep order:false, stats:pseudo
6 changes: 6 additions & 0 deletions tests/integrationtest/t/planner/core/indexmerge_path.test
Original file line number Diff line number Diff line change
Expand Up @@ -589,3 +589,9 @@ explain format='plan_tree' select /*+ use_index_merge(t, idx_ac, idx_bc) */ * fr
select /*+ use_index_merge(t, idx_ac, idx_bc) */ * from t where a = 1 or b > 5 order by c limit 3;
explain format='plan_tree' select /*+ use_index_merge(t, idx_ac, idx_bc) */ * from t where a = 1 or b > 5 order by c limit 3 offset 1;
select /*+ use_index_merge(t, idx_ac, idx_bc) */ * from t where a = 1 or b > 5 order by c limit 3 offset 1;

# TestIndexMergeINInORList
drop table if exists t1;
create table t1(a int, b int, c int, d int, e int, index iea(e,a), index ieb(e,b), index iec(e,c), index ied(e,d));
explain format = 'plan_tree' select /*+ use_index_merge(t1) */ * from t1 where e = 1 and (a in (1,2,3) or b in (2,3,4) or c in (3,4,5));
explain format = 'plan_tree' select /*+ use_index_merge(t1) */ * from t1 where e = 1 and (a in (1,2,3) or b in (2,3,4) or c in (3,4,5)) limit 3;
Loading