Skip to content

Commit

Permalink
planner: remove some restrictions for global index (#53509)
Browse files Browse the repository at this point in the history
ref #45133
  • Loading branch information
Defined2014 authored May 24, 2024
1 parent 81f4141 commit 027de7a
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 18 deletions.
18 changes: 10 additions & 8 deletions pkg/planner/core/find_best_task.go
Original file line number Diff line number Diff line change
Expand Up @@ -2046,15 +2046,17 @@ func (ds *DataSource) convertToIndexScan(prop *property.PhysicalProperty,
}

if ds.tableInfo.GetPartitionInfo() != nil {
// Add sort items for index scan for merge-sort operation between partitions.
byItems := make([]*util.ByItems, 0, len(prop.SortItems))
for _, si := range prop.SortItems {
byItems = append(byItems, &util.ByItems{
Expr: si.Col,
Desc: si.Desc,
})
// Add sort items for index scan for merge-sort operation between partitions, only required for local index.
if !is.Index.Global {
byItems := make([]*util.ByItems, 0, len(prop.SortItems))
for _, si := range prop.SortItems {
byItems = append(byItems, &util.ByItems{
Expr: si.Col,
Desc: si.Desc,
})
}
cop.indexPlan.(*PhysicalIndexScan).ByItems = byItems
}
cop.indexPlan.(*PhysicalIndexScan).ByItems = byItems
if cop.tablePlan != nil && ds.SCtx().GetSessionVars().StmtCtx.UseDynamicPartitionPrune() {
if !is.Index.Global {
is.Columns, is.schema, _ = AddExtraPhysTblIDColumn(is.SCtx(), is.Columns, is.Schema())
Expand Down
10 changes: 0 additions & 10 deletions pkg/planner/core/indexmerge_path.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,13 +156,6 @@ func (ds *DataSource) generateNormalIndexPartialPaths4DNF(
// the entire index merge is not valid anymore.
return nil, false, usedMap
}
// prune out global indexes.
itemPaths = slices.DeleteFunc(itemPaths, func(path *util.AccessPath) bool {
if path.Index != nil && path.Index.Global {
return true
}
return false
})
partialPath := buildIndexMergePartialPath(itemPaths)
if partialPath == nil {
// for this dnf item, we couldn't generate an index merge partial path.
Expand Down Expand Up @@ -889,9 +882,6 @@ func (ds *DataSource) generateIndexMerge4ComposedIndex(normalPathCnt int, indexM
var mvIndexPathCnt int
candidateAccessPaths := make([]*util.AccessPath, 0, len(ds.possibleAccessPaths))
for idx := 0; idx < normalPathCnt; idx++ {
if ds.possibleAccessPaths[idx].Index != nil && ds.possibleAccessPaths[idx].Index.Global {
continue
}
if (ds.possibleAccessPaths[idx].IsTablePath() &&
!ds.isInIndexMergeHints("primary")) ||
(!ds.possibleAccessPaths[idx].IsTablePath() &&
Expand Down
55 changes: 55 additions & 0 deletions tests/integrationtest/r/globalindex/multi_valued_index.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
set tidb_enable_global_index = true;
CREATE TABLE `customers` (
`id` bigint(20),
`name` char(10) DEFAULT NULL,
`custinfo` json DEFAULT NULL,
KEY idx(`id`),
UNIQUE KEY `zips` ((cast(json_extract(`custinfo`, _utf8'$.zipcode') as unsigned array)))
) PARTITION BY HASH (`id`) PARTITIONS 5;
INSERT INTO customers VALUES (1, 'pingcap', '{"zipcode": [1,2]}');
INSERT INTO customers VALUES (2, 'pingcap', '{"zipcode": [2,3]}');
Error 1062 (23000): Duplicate entry '2' for key 'customers.zips'
INSERT INTO customers VALUES (2, 'pingcap', '{"zipcode": [3,3,4]}');
INSERT INTO customers VALUES (3, 'pingcap', '{"zipcode": [5,6]}');
explain select * from customers where (1 member of (custinfo->'$.zipcode'));
id estRows task access object operator info
IndexMerge_11 1.00 root partition:all type: union
├─IndexRangeScan_8(Build) 1.00 cop[tikv] table:customers, index:zips(cast(json_extract(`custinfo`, _utf8'$.zipcode') as unsigned array)) range:[1,1], keep order:false, stats:pseudo
└─TableRowIDScan_10(Probe) 1.00 cop[tikv] table:customers keep order:false, stats:pseudo
select * from customers where (1 member of (custinfo->'$.zipcode'));
id name custinfo
1 pingcap {"zipcode": [1, 2]}
explain select * from customers where json_overlaps("[1, 3, 7, 10]", custinfo->'$.zipcode');
id estRows task access object operator info
Selection_5 3.20 root json_overlaps(cast("[1, 3, 7, 10]", json BINARY), json_extract(globalindex__multi_valued_index.customers.custinfo, "$.zipcode"))
└─IndexMerge_17 4.00 root partition:all type: union
├─IndexRangeScan_8(Build) 1.00 cop[tikv] table:customers, index:zips(cast(json_extract(`custinfo`, _utf8'$.zipcode') as unsigned array)) range:[1,1], keep order:false, stats:pseudo
├─IndexRangeScan_10(Build) 1.00 cop[tikv] table:customers, index:zips(cast(json_extract(`custinfo`, _utf8'$.zipcode') as unsigned array)) range:[3,3], keep order:false, stats:pseudo
├─IndexRangeScan_12(Build) 1.00 cop[tikv] table:customers, index:zips(cast(json_extract(`custinfo`, _utf8'$.zipcode') as unsigned array)) range:[7,7], keep order:false, stats:pseudo
├─IndexRangeScan_14(Build) 1.00 cop[tikv] table:customers, index:zips(cast(json_extract(`custinfo`, _utf8'$.zipcode') as unsigned array)) range:[10,10], keep order:false, stats:pseudo
└─TableRowIDScan_16(Probe) 4.00 cop[tikv] table:customers keep order:false, stats:pseudo
select * from customers where json_overlaps("[1, 3, 7, 10]", custinfo->'$.zipcode');
id name custinfo
1 pingcap {"zipcode": [1, 2]}
2 pingcap {"zipcode": [3, 3, 4]}
explain select * from customers where json_overlaps("[1, 6, 10]", custinfo->'$.zipcode') and id > 1;
id estRows task access object operator info
Selection_5 2.40 root json_overlaps(cast("[1, 6, 10]", json BINARY), json_extract(globalindex__multi_valued_index.customers.custinfo, "$.zipcode"))
└─IndexMerge_20 1.00 root partition:all type: union
├─IndexRangeScan_12(Build) 1.00 cop[tikv] table:customers, index:zips(cast(json_extract(`custinfo`, _utf8'$.zipcode') as unsigned array)) range:[1,1], keep order:false, stats:pseudo
├─IndexRangeScan_14(Build) 1.00 cop[tikv] table:customers, index:zips(cast(json_extract(`custinfo`, _utf8'$.zipcode') as unsigned array)) range:[6,6], keep order:false, stats:pseudo
├─IndexRangeScan_16(Build) 1.00 cop[tikv] table:customers, index:zips(cast(json_extract(`custinfo`, _utf8'$.zipcode') as unsigned array)) range:[10,10], keep order:false, stats:pseudo
└─Selection_19(Probe) 1.00 cop[tikv] gt(globalindex__multi_valued_index.customers.id, 1)
└─TableRowIDScan_18 3.00 cop[tikv] table:customers keep order:false, stats:pseudo
select * from customers where json_overlaps("[1, 6, 10]", custinfo->'$.zipcode') and id > 1;
id name custinfo
3 pingcap {"zipcode": [5, 6]}
explain select /*+ USE_INDEX_MERGE(customers, idx, zips) */* from customers where (1 member of (custinfo->'$.zipcode')) and id > 0;
id estRows task access object operator info
IndexMerge_9 0.33 root partition:all type: intersection
├─IndexRangeScan_5(Build) 3333.33 cop[tikv] table:customers, index:idx(id) range:(0,+inf], keep order:false, stats:pseudo
├─IndexRangeScan_6(Build) 1.00 cop[tikv] table:customers, index:zips(cast(json_extract(`custinfo`, _utf8'$.zipcode') as unsigned array)) range:[1,1], keep order:false, stats:pseudo
└─TableRowIDScan_8(Probe) 0.33 cop[tikv] table:customers keep order:false, stats:pseudo
select /*+ USE_INDEX_MERGE(customers, idx, zips) */* from customers where (1 member of (custinfo->'$.zipcode')) and id > 0;
id name custinfo
1 pingcap {"zipcode": [1, 2]}
28 changes: 28 additions & 0 deletions tests/integrationtest/t/globalindex/multi_valued_index.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
set tidb_enable_global_index = true;
CREATE TABLE `customers` (
`id` bigint(20),
`name` char(10) DEFAULT NULL,
`custinfo` json DEFAULT NULL,
KEY idx(`id`),
UNIQUE KEY `zips` ((cast(json_extract(`custinfo`, _utf8'$.zipcode') as unsigned array)))
) PARTITION BY HASH (`id`) PARTITIONS 5;

INSERT INTO customers VALUES (1, 'pingcap', '{"zipcode": [1,2]}');
--error 1062
INSERT INTO customers VALUES (2, 'pingcap', '{"zipcode": [2,3]}');
INSERT INTO customers VALUES (2, 'pingcap', '{"zipcode": [3,3,4]}');
INSERT INTO customers VALUES (3, 'pingcap', '{"zipcode": [5,6]}');

explain select * from customers where (1 member of (custinfo->'$.zipcode'));
select * from customers where (1 member of (custinfo->'$.zipcode'));

explain select * from customers where json_overlaps("[1, 3, 7, 10]", custinfo->'$.zipcode');
--sorted_result
select * from customers where json_overlaps("[1, 3, 7, 10]", custinfo->'$.zipcode');

explain select * from customers where json_overlaps("[1, 6, 10]", custinfo->'$.zipcode') and id > 1;
--sorted_result
select * from customers where json_overlaps("[1, 6, 10]", custinfo->'$.zipcode') and id > 1;

explain select /*+ USE_INDEX_MERGE(customers, idx, zips) */* from customers where (1 member of (custinfo->'$.zipcode')) and id > 0;
select /*+ USE_INDEX_MERGE(customers, idx, zips) */* from customers where (1 member of (custinfo->'$.zipcode')) and id > 0;

0 comments on commit 027de7a

Please sign in to comment.