Skip to content

Commit

Permalink
push filter down index scan (#5019)
Browse files Browse the repository at this point in the history
* push filter down index scan

* fix bug

Co-authored-by: Sophie <[email protected]>
  • Loading branch information
jievince and Sophie-Xie authored Dec 8, 2022
1 parent 5057eeb commit 55212e2
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 9 deletions.
30 changes: 24 additions & 6 deletions src/graph/optimizer/rule/PushLimitDownScanAppendVerticesRule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#include "graph/planner/plan/Query.h"

using nebula::graph::AppendVertices;
using nebula::graph::Explore;
using nebula::graph::IndexScan;
using nebula::graph::Limit;
using nebula::graph::PlanNode;
using nebula::graph::QueryContext;
Expand All @@ -19,7 +21,8 @@ using nebula::graph::ScanVertices;
namespace nebula {
namespace opt {

// Limit->AppendVertices->ScanVertices ==> Limit->AppendVertices->ScanVertices(Limit)
// Limit->AppendVertices->ScanVertices/IndexScan ==>
// Limit->AppendVertices->ScanVertices/IndexScan(Limit)

std::unique_ptr<OptRule> PushLimitDownScanAppendVerticesRule::kInstance =
std::unique_ptr<PushLimitDownScanAppendVerticesRule>(new PushLimitDownScanAppendVerticesRule());
Expand All @@ -32,7 +35,8 @@ const Pattern &PushLimitDownScanAppendVerticesRule::pattern() const {
static Pattern pattern =
Pattern::create(graph::PlanNode::Kind::kLimit,
{Pattern::create(graph::PlanNode::Kind::kAppendVertices,
{Pattern::create(graph::PlanNode::Kind::kScanVertices)})});
{Pattern::create({graph::PlanNode::Kind::kScanVertices,
graph::PlanNode::Kind::kIndexScan})})});
return pattern;
}

Expand All @@ -53,8 +57,22 @@ bool PushLimitDownScanAppendVerticesRule::match(OptContext *ctx,
}
auto *filter = av->filter();
auto *vFilter = av->vFilter();
// Limit can't push over filter operation
return filter == nullptr && vFilter == nullptr;

if (vFilter != nullptr) return false;
if (filter == nullptr) return true;
auto scanNode = matched.planNode({0, 0, 0});
if (scanNode->kind() == PlanNode::Kind::kScanVertices) return false;
// If the scanNode is kIndexScan, and the filter looks like `player._tag IS NOT EMPTY`,
// the limit could also be pushed down
if (filter->kind() != Expression::Kind::kIsNotEmpty) {
return false;
}
auto *isNotEmpty = static_cast<const UnaryExpression *>(filter);
auto *operand = isNotEmpty->operand();
if (operand->kind() != Expression::Kind::kTagProperty) {
return false;
}
return true;
}

StatusOr<OptRule::TransformResult> PushLimitDownScanAppendVerticesRule::transform(
Expand All @@ -65,7 +83,7 @@ StatusOr<OptRule::TransformResult> PushLimitDownScanAppendVerticesRule::transfor

const auto limit = static_cast<const Limit *>(limitGroupNode->node());
const auto appendVertices = static_cast<const AppendVertices *>(appendVerticesGroupNode->node());
const auto scanVertices = static_cast<const ScanVertices *>(scanVerticesGroupNode->node());
const auto scanVertices = static_cast<const Explore *>(scanVerticesGroupNode->node());

int64_t limitRows = limit->offset() + limit->count();
if (scanVertices->limit() >= 0 && limitRows >= scanVertices->limit()) {
Expand All @@ -80,7 +98,7 @@ StatusOr<OptRule::TransformResult> PushLimitDownScanAppendVerticesRule::transfor
auto newAppendVerticesGroup = OptGroup::create(octx);
auto newAppendVerticesGroupNode = newAppendVerticesGroup->makeGroupNode(newAppendVertices);

auto newScanVertices = static_cast<ScanVertices *>(scanVertices->clone());
auto newScanVertices = static_cast<Explore *>(scanVertices->clone());
newScanVertices->setLimit(limitRows);
auto newScanVerticesGroup = OptGroup::create(octx);
auto newScanVerticesGroupNode = newScanVerticesGroup->makeGroupNode(newScanVertices);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ namespace opt {
// | AppendVertices |
// +---------+---------+
// |
// +---------+---------+
// | ScanVertices |
// +---------+---------+
// +---------+-------------------+
// | ScanVertices/IndexScan |
// +---------+-------------------+
//
// After:
//
Expand All @@ -47,6 +47,7 @@ namespace opt {
// |
// +---------+---------+
// | ScanVertices |
// |    IndexScan |
// | (limit=3) |
// +---------+---------+

Expand Down
22 changes: 22 additions & 0 deletions tests/tck/features/match/Base.feature
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,22 @@ Feature: Basic match
Then the result should be, in any order, with relax comparison:
| v |
| ("Yao Ming") |
When profiling query:
"""
MATCH (v:player) RETURN v.player.age LIMIT 3
"""
Then the result should be, in any order, with relax comparison:
| v.player.age |
| /\d+/ |
| /\d+/ |
| /\d+/ |
Then the execution plan should be:
| id | name | dependencies | operator info |
| 5 | Project | 4 | |
| 4 | Limit | 3 | {"offset": "0", "count": "3"} |
| 3 | AppendVertices | 2 | |
| 2 | IndexScan | 1 | {"limit": "3"} |
| 1 | Start | | |
When executing query:
"""
MATCH (v:player) WHERE v.player.age < 0 RETURN v
Expand Down Expand Up @@ -629,6 +645,12 @@ Feature: Basic match
MATCH (v:player:bachelor) RETURN v
"""
Then a ExecutionError should be raised at runtime: Scan vertices or edges need to specify a limit number, or limit number can not push down.
# TODO(jie): Optimize this case
When executing query:
"""
MATCH (v) WHERE v.player.age == 18 RETURN v LIMIT 3
"""
Then a ExecutionError should be raised at runtime: Scan vertices or edges need to specify a limit number, or limit number can not push down.
When executing query:
"""
MATCH (v:player{age:23}:bachelor) RETURN v
Expand Down

0 comments on commit 55212e2

Please sign in to comment.