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

fix index degeneration #3311

Merged
merged 12 commits into from
Nov 23, 2021
14 changes: 6 additions & 8 deletions src/graph/optimizer/rule/IndexScanRule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,10 @@ StatusOr<OptRule::TransformResult> IndexScanRule::transform(OptContext* ctx,
FilterItems items;
ScanKind kind;
NG_RETURN_IF_ERROR(analyzeExpression(filter, &items, &kind, isEdge(groupNode)));
NG_RETURN_IF_ERROR(createIndexQueryCtx(iqctx, kind, items, qctx, groupNode));
auto status = createIndexQueryCtx(iqctx, kind, items, qctx, groupNode);
if (!status.ok()) {
NG_RETURN_IF_ERROR(createIndexQueryCtx(iqctx, qctx, groupNode));
}
}

const auto* oldIN = groupNode->node();
Expand Down Expand Up @@ -481,20 +484,15 @@ std::vector<IndexItem> IndexScanRule::findValidIndex(graph::QueryContext* qctx,
std::vector<IndexItem> validIndexes;
// Find indexes for match all fields by where condition.
for (const auto& index : indexes) {
bool allColsHint = true;
const auto& fields = index->get_fields();
for (const auto& item : items.items) {
auto it = std::find_if(fields.begin(), fields.end(), [item](const auto& field) {
return field.get_name() == item.col_;
});
if (it == fields.end()) {
allColsHint = false;
break;
if (it != fields.end()) {
validIndexes.emplace_back(index);
}
}
if (allColsHint) {
validIndexes.emplace_back(index);
}
}
// If the first field of the index does not match any condition, the index is
// invalid. remove it from validIndexes.
Expand Down
99 changes: 99 additions & 0 deletions tests/tck/features/match/IndexSelecting.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# Copyright (c) 2021 vesoft inc. All rights reserved.
#
# This source code is licensed under Apache 2.0 License.
Feature: Index selecting for match statement

Background: Prepare a new space
Given an empty graph
And create a space with following options:
| partition_num | 9 |
| replica_factor | 1 |
| vid_type | FIXED_STRING(30) |
| charset | utf8 |
| collate | utf8_bin |
And having executed:
"""
CREATE tag player(name string, age int, score int, gender bool);
"""
And having executed:
"""
INSERT VERTEX player(name, age, score, gender) VALUES "Tim Duncan":("Tim Duncan", 42, 28, true),"Yao Ming":("Yao Ming", 38, 23, true),"Nneka Ogwumike":("Nneka Ogwumike", 35, 13, false);
"""
And having executed:
"""
create tag index player_index on player();
create tag index player_name_index on player(name(8));
create tag index player_age_name_index on player(age,name(8));
"""
And wait 3 seconds

Scenario: Test Index selecting
When submit a job:
"""
rebuild tag index player_index;
"""
Then wait the job to finish
When submit a job:
"""
rebuild tag index player_name_index;
"""
Then wait the job to finish
When submit a job:
"""
rebuild tag index player_age_name_index;
"""
Then wait the job to finish
# Prefix Index
When profiling query:
"""
MATCH (v:player {name: "Yao Ming"}) RETURN v.name AS name
"""
Then the result should be, in any order, with relax comparison:
| name |
| "Yao Ming" |
And the execution plan should be:
| id | name | dependencies | operator info |
| 6 | Project | 2 | |
| 2 | AppendVertices | 5 | |
| 5 | IndexScan | 0 | {"indexCtx": {"columnHints":{"scanType":"PREFIX"}}} |
| 0 | Start | | |
# Range Index
When profiling query:
"""
MATCH (v:player) WHERE v.name > "Tim" and v.name < "Zom" RETURN v.name AS name
"""
Then the result should be, in any order, with relax comparison:
| name |
| "Yao Ming" |
| "Tim Duncan" |
And the execution plan should be:
| id | name | dependencies | operator info |
| 9 | Project | 7 | |
| 7 | Filter | 2 | |
| 2 | AppendVertices | 6 | |
| 6 | IndexScan | 0 | {"indexCtx": {"columnHints":{"scanType":"RANGE"}}} |
| 0 | Start | | |
# Degeneration to FullScan Index
When executing query:
"""
MATCH (v:player) WHERE v.score < 20 RETURN v.name AS name
"""
Then the result should be, in any order, with relax comparison:
| name |
| "Nneka Ogwumike" |
# Degeneration to Prefix Index
When profiling query:
"""
MATCH (v:player) WHERE v.name == "Tim Duncan" and v.score == 28 RETURN v.name AS name
"""
Then the result should be, in any order, with relax comparison:
| name |
| "Tim Duncan" |
And the execution plan should be:
| id | name | dependencies | operator info |
| 9 | Project | 7 | |
| 7 | Filter | 2 | |
| 2 | AppendVertices | 6 | |
| 6 | IndexScan | 0 | {"indexCtx": {"columnHints":{"scanType":"PREFIX"}}} |
| 0 | Start | | |
Then drop the used space