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

Feature/index scan limit push down #2823

Closed
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
6763494
Add the polymorphsim mechanism for plan node.
Shylock-Hg Sep 7, 2021
0cd521a
Merge branch 'master' into feature/node-polymorphsim
Shylock-Hg Sep 7, 2021
2ba7820
Fix the typo.
Shylock-Hg Sep 7, 2021
5f900d9
Merge branch 'feature/node-polymorphsim' into feature/index-scan-limi…
Shylock-Hg Sep 7, 2021
3f78095
Correct the singleton mt-safe.
Shylock-Hg Sep 8, 2021
12b5c3a
Merge branch 'feature/node-polymorphsim' of github.com:Shylock-Hg/neb…
Shylock-Hg Sep 8, 2021
eec2f75
Merge branch 'feature/node-polymorphsim' into feature/index-scan-limi…
Shylock-Hg Sep 8, 2021
30f68e5
Push limit to IndexScan.
Shylock-Hg Sep 8, 2021
91e807e
Merge branch 'master' of https://github.com/vesoft-inc/nebula into fe…
Shylock-Hg Sep 8, 2021
03b70a1
Push down to storage.
Shylock-Hg Sep 8, 2021
017356a
Merge branch 'master' into feature/index-scan-limit-push-down
Shylock-Hg Sep 15, 2021
2fb34dd
Merge branch 'master' of https://github.com/vesoft-inc/nebula into fe…
Shylock-Hg Sep 15, 2021
900b88d
Merge branch 'master' into feature/index-scan-limit-push-down
Shylock-Hg Sep 15, 2021
eb708d0
Merge branch 'master' into feature/index-scan-limit-push-down
Shylock-Hg Sep 16, 2021
e910d28
Merge branch 'master' into feature/index-scan-limit-push-down
Shylock-Hg Sep 16, 2021
a5534ea
Limit clause for lookup sentence.
Shylock-Hg Sep 16, 2021
fa879b7
Merge branch 'master' into feature/index-scan-limit-push-down
Shylock-Hg Sep 16, 2021
68bff72
Remove the unused include.
Shylock-Hg Sep 16, 2021
a34eaf7
Merge branch 'feature/index-scan-limit-push-down' of github.com:Shylo…
Shylock-Hg Sep 16, 2021
94055ca
Add method to check base type.
Shylock-Hg Sep 27, 2021
b15ad09
Merge branch 'master' into feature/index-scan-limit-push-down
Shylock-Hg Sep 27, 2021
6a5fb69
Merge branch 'master' of https://github.com/vesoft-inc/nebula into fe…
Shylock-Hg Sep 27, 2021
4b995d8
Reserve space for query kind.
Shylock-Hg Sep 27, 2021
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
2 changes: 2 additions & 0 deletions src/clients/storage/GraphStorageClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,7 @@ folly::SemiFuture<StorageRpcResponse<cpp2::LookupIndexResp>> GraphStorageClient:
bool isEdge,
int32_t tagOrEdge,
const std::vector<std::string>& returnCols,
int64_t limit,
folly::EventBase* evb) {
// TODO(sky) : instead of isEdge and tagOrEdge to nebula::cpp2::SchemaID for graph layer.
auto status = getHostParts(space);
Expand Down Expand Up @@ -520,6 +521,7 @@ folly::SemiFuture<StorageRpcResponse<cpp2::LookupIndexResp>> GraphStorageClient:
spec.set_schema_id(schemaId);
req.set_indices(spec);
req.set_common(common);
req.set_limit(limit);
}

return collectResponse(
Expand Down
1 change: 1 addition & 0 deletions src/clients/storage/GraphStorageClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ class GraphStorageClient : public StorageClientBase<cpp2::GraphStorageServiceAsy
bool isEdge,
int32_t tagOrEdge,
const std::vector<std::string>& returnCols,
int64_t limit,
folly::EventBase* evb = nullptr);

folly::SemiFuture<StorageRpcResponse<cpp2::GetNeighborsResponse>> lookupAndTraverse(
Expand Down
3 changes: 2 additions & 1 deletion src/graph/executor/query/IndexScanExecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ folly::Future<Status> IndexScanExecutor::indexScan() {
ictxs,
lookup->isEdge(),
lookup->schemaId(),
lookup->returnColumns())
lookup->returnColumns(),
lookup->limit())
.via(runner())
.thenValue([this](StorageRpcResponse<LookupIndexResp> &&rpcResp) {
addStats(rpcResp, otherStats_);
Expand Down
3 changes: 2 additions & 1 deletion src/graph/optimizer/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ nebula_add_library(
rule/MergeGetNbrsAndDedupRule.cpp
rule/MergeGetNbrsAndProjectRule.cpp
rule/IndexScanRule.cpp
rule/LimitPushDownRule.cpp
rule/PushLimitDownGetNeighborsRule.cpp
rule/TopNRule.cpp
rule/PushFilterDownAggregateRule.cpp
rule/PushFilterDownProjectRule.cpp
Expand All @@ -33,6 +33,7 @@ nebula_add_library(
rule/IndexFullScanBaseRule.cpp
rule/TagIndexFullScanRule.cpp
rule/EdgeIndexFullScanRule.cpp
rule/PushLimitDownIndexScanRule.cpp
)

nebula_add_subdirectory(test)
7 changes: 5 additions & 2 deletions src/graph/optimizer/OptRule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,20 @@ const PlanNode *MatchedResult::planNode(const std::vector<int32_t> &pos) const {
return DCHECK_NOTNULL(result->node)->node();
}

Pattern Pattern::create(graph::PlanNode::Kind kind, std::initializer_list<Pattern> patterns) {
Pattern Pattern::create(graph::PlanNode::Kind kind,
std::initializer_list<Pattern> patterns,
bool polymorphism) {
Pattern pattern;
pattern.kind_ = kind;
for (auto &p : patterns) {
pattern.dependencies_.emplace_back(p);
}
pattern.polymorphism_ = polymorphism;
return pattern;
}

StatusOr<MatchedResult> Pattern::match(const OptGroupNode *groupNode) const {
if (groupNode->node()->kind() != kind_) {
if (!(polymorphism_ ? groupNode->node()->isA(kind_) : groupNode->node()->kind() == kind_)) {
return Status::Error();
}

Expand Down
6 changes: 5 additions & 1 deletion src/graph/optimizer/OptRule.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ struct MatchedResult {

class Pattern final {
public:
static Pattern create(graph::PlanNode::Kind kind, std::initializer_list<Pattern> patterns = {});
static Pattern create(graph::PlanNode::Kind kind,
std::initializer_list<Pattern> patterns = {},
bool polymorphism = false);

StatusOr<MatchedResult> match(const OptGroupNode *groupNode) const;

Expand All @@ -55,6 +57,8 @@ class Pattern final {

graph::PlanNode::Kind kind_;
std::vector<Pattern> dependencies_;
// Whether enable plymorphsim plan node match
bool polymorphism_{false};
};

class OptRule {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* attached with Common Clause Condition 1.0, found in the LICENSES directory.
*/

#include "graph/optimizer/rule/LimitPushDownRule.h"
#include "graph/optimizer/rule/PushLimitDownGetNeighborsRule.h"

#include "common/expression/BinaryExpression.h"
#include "common/expression/ConstantExpression.h"
Expand All @@ -27,20 +27,22 @@ using nebula::graph::QueryContext;
namespace nebula {
namespace opt {

std::unique_ptr<OptRule> LimitPushDownRule::kInstance =
std::unique_ptr<LimitPushDownRule>(new LimitPushDownRule());
std::unique_ptr<OptRule> PushLimitDownGetNeighborsRule::kInstance =
std::unique_ptr<PushLimitDownGetNeighborsRule>(new PushLimitDownGetNeighborsRule());

LimitPushDownRule::LimitPushDownRule() { RuleSet::QueryRules().addRule(this); }
PushLimitDownGetNeighborsRule::PushLimitDownGetNeighborsRule() {
RuleSet::QueryRules().addRule(this);
}

const Pattern &LimitPushDownRule::pattern() const {
const Pattern &PushLimitDownGetNeighborsRule::pattern() const {
static Pattern pattern =
Pattern::create(graph::PlanNode::Kind::kLimit,
{Pattern::create(graph::PlanNode::Kind::kProject,
{Pattern::create(graph::PlanNode::Kind::kGetNeighbors)})});
return pattern;
}

StatusOr<OptRule::TransformResult> LimitPushDownRule::transform(
StatusOr<OptRule::TransformResult> PushLimitDownGetNeighborsRule::transform(
OptContext *octx, const MatchedResult &matched) const {
auto limitGroupNode = matched.node;
auto projGroupNode = matched.dependencies.front().node;
Expand Down Expand Up @@ -79,7 +81,9 @@ StatusOr<OptRule::TransformResult> LimitPushDownRule::transform(
return result;
}

std::string LimitPushDownRule::toString() const { return "LimitPushDownRule"; }
std::string PushLimitDownGetNeighborsRule::toString() const {
return "PushLimitDownGetNeighborsRule";
}

} // namespace opt
} // namespace nebula
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
* attached with Common Clause Condition 1.0, found in the LICENSES directory.
*/

#ifndef GRAPH_OPTIMIZER_RULE_LIMITPUSHDOWN_H_
#define GRAPH_OPTIMIZER_RULE_LIMITPUSHDOWN_H_
#pragma once

#include <memory>

Expand All @@ -14,7 +13,7 @@
namespace nebula {
namespace opt {

class LimitPushDownRule final : public OptRule {
class PushLimitDownGetNeighborsRule final : public OptRule {
public:
const Pattern &pattern() const override;

Expand All @@ -24,12 +23,10 @@ class LimitPushDownRule final : public OptRule {
std::string toString() const override;

private:
LimitPushDownRule();
PushLimitDownGetNeighborsRule();

static std::unique_ptr<OptRule> kInstance;
};

} // namespace opt
} // namespace nebula

#endif // GRAPH_OPTIMIZER_RULE_LIMITPUSHDOWN_H_
85 changes: 85 additions & 0 deletions src/graph/optimizer/rule/PushLimitDownIndexScanRule.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/* Copyright (c) 2021 vesoft inc. All rights reserved.
*
* This source code is licensed under Apache 2.0 License,
* attached with Common Clause Condition 1.0, found in the LICENSES directory.
*/

#include "graph/optimizer/rule/PushLimitDownIndexScanRule.h"

#include "common/expression/BinaryExpression.h"
#include "common/expression/ConstantExpression.h"
#include "common/expression/Expression.h"
#include "common/expression/FunctionCallExpression.h"
#include "common/expression/LogicalExpression.h"
#include "common/expression/UnaryExpression.h"
#include "graph/optimizer/OptContext.h"
#include "graph/optimizer/OptGroup.h"
#include "graph/planner/plan/PlanNode.h"
#include "graph/planner/plan/Query.h"
#include "graph/visitor/ExtractFilterExprVisitor.h"

using nebula::graph::IndexScan;
using nebula::graph::Limit;
using nebula::graph::PlanNode;
using nebula::graph::Project;
using nebula::graph::QueryContext;

namespace nebula {
namespace opt {

std::unique_ptr<OptRule> PushLimitDownIndexScanRule::kInstance =
std::unique_ptr<PushLimitDownIndexScanRule>(new PushLimitDownIndexScanRule());

PushLimitDownIndexScanRule::PushLimitDownIndexScanRule() { RuleSet::QueryRules().addRule(this); }

const Pattern &PushLimitDownIndexScanRule::pattern() const {
static Pattern pattern = Pattern::create(
graph::PlanNode::Kind::kLimit,
{Pattern::create(graph::PlanNode::Kind::kProject,
{Pattern::create(graph::PlanNode::Kind::kIndexScan, {}, true)})});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here should not be one opt rule, but should be split into two rules: limit <-> project, limit -> indexscan

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why need limit->indexscan?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Push limit down indexscan

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sentence only generate limit->project->indexscan plan

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should consider the optimization rules from the perspective of the optimizer, not just for this case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need to match the nonexistent pattern.

return pattern;
}

StatusOr<OptRule::TransformResult> PushLimitDownIndexScanRule::transform(
OptContext *octx, const MatchedResult &matched) const {
auto limitGroupNode = matched.node;
auto projGroupNode = matched.dependencies.front().node;
auto indexScanGroupNode = matched.dependencies.front().dependencies.front().node;

const auto limit = limitGroupNode->node()->asNode<const Limit>();
const auto proj = projGroupNode->node()->asNode<const Project>();
const auto indexScan = indexScanGroupNode->node()->asNode<const IndexScan>();

int64_t limitRows = limit->offset() + limit->count();
critical27 marked this conversation as resolved.
Show resolved Hide resolved
if (indexScan->limit() >= 0 && limitRows >= indexScan->limit()) {
return TransformResult::noTransform();
}

auto newLimit = static_cast<Limit *>(limit->clone());
auto newLimitGroupNode = OptGroupNode::create(octx, newLimit, limitGroupNode->group());

auto newProj = static_cast<Project *>(proj->clone());
auto newProjGroup = OptGroup::create(octx);
auto newProjGroupNode = newProjGroup->makeGroupNode(newProj);

auto newIndexScan = static_cast<IndexScan *>(indexScan->clone());
newIndexScan->setLimit(limitRows);
auto newIndexScanGroup = OptGroup::create(octx);
auto newIndexScanGroupNode = newIndexScanGroup->makeGroupNode(newIndexScan);

newLimitGroupNode->dependsOn(newProjGroup);
newProjGroupNode->dependsOn(newIndexScanGroup);
for (auto dep : indexScanGroupNode->dependencies()) {
newIndexScanGroupNode->dependsOn(dep);
}

TransformResult result;
result.eraseAll = true;
result.newGroupNodes.emplace_back(newLimitGroupNode);
return result;
}

std::string PushLimitDownIndexScanRule::toString() const { return "PushLimitDownIndexScanRule"; }

} // namespace opt
} // namespace nebula
32 changes: 32 additions & 0 deletions src/graph/optimizer/rule/PushLimitDownIndexScanRule.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/* Copyright (c) 2021 vesoft inc. All rights reserved.
*
* This source code is licensed under Apache 2.0 License,
* attached with Common Clause Condition 1.0, found in the LICENSES directory.
*/

#pragma once

#include <memory>

#include "graph/optimizer/OptRule.h"

namespace nebula {
namespace opt {

class PushLimitDownIndexScanRule final : public OptRule {
public:
const Pattern &pattern() const override;

StatusOr<OptRule::TransformResult> transform(OptContext *ctx,
const MatchedResult &matched) const override;

std::string toString() const override;

private:
PushLimitDownIndexScanRule();

static std::unique_ptr<OptRule> kInstance;
};

} // namespace opt
} // namespace nebula
Loading