forked from vesoft-inc/nebula
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Split optimizer rules (vesoft-inc#2574)
<!-- Thanks for your contribution! In order to review PR more efficiently, please add information according to the template. --> ## What type of PR is this? - [ ] bug - [ ] feature - [x] enhancement ## What problem(s) does this PR solve? Split the optimizer rule `PushFilterDownTraverseRule` to `PushFilterThroughAppendVerticesRule` and `PushFilterDownTraverseRule`. This pr is for refactoring purposes but also introduces some optimizations, such as non-endpoint predicates that can be pushed down before AppendVertices. The purpose of refactoring is that the previous implementation was too ad-hoc for further optimization, and there were some conflicts between rules, so we should try to avoid similar code implementation from a more common perspective, especially for the development of optimizer. ## Checklist: Tests: - [ ] Unit test(positive and negative cases) - [ ] Function test - [ ] Performance test - [ ] N/A Affects: - [ ] Documentation affected (Please add the label if documentation needs to be modified.) - [ ] Incompatibility (If it breaks the compatibility, please describe it and add the label.) - [ ] If it's needed to cherry-pick (If cherry-pick to some branches is required, please label the destination version(s).) - [ ] Performance impacted: Consumes more CPU/Memory Migrated from vesoft-inc#5470 Co-authored-by: kyle.cao <[email protected]>
- Loading branch information
1 parent
661278e
commit 7b2a481
Showing
16 changed files
with
326 additions
and
138 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
123 changes: 123 additions & 0 deletions
123
src/graph/optimizer/rule/PushFilterThroughAppendVerticesRule.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
/* Copyright (c) 2023 vesoft inc. All rights reserved. | ||
* | ||
* This source code is licensed under Apache 2.0 License. | ||
*/ | ||
|
||
#include "graph/optimizer/rule/PushFilterThroughAppendVerticesRule.h" | ||
|
||
#include "common/expression/Expression.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/util/ExpressionUtils.h" | ||
#include "graph/visitor/ExtractFilterExprVisitor.h" | ||
|
||
using nebula::Expression; | ||
using nebula::graph::AppendVertices; | ||
using nebula::graph::Filter; | ||
using nebula::graph::PlanNode; | ||
using nebula::graph::QueryContext; | ||
|
||
namespace nebula { | ||
namespace opt { | ||
|
||
std::unique_ptr<OptRule> PushFilterThroughAppendVerticesRule::kInstance = | ||
std::unique_ptr<PushFilterThroughAppendVerticesRule>(new PushFilterThroughAppendVerticesRule()); | ||
|
||
PushFilterThroughAppendVerticesRule::PushFilterThroughAppendVerticesRule() { | ||
RuleSet::QueryRules().addRule(this); | ||
} | ||
|
||
const Pattern& PushFilterThroughAppendVerticesRule::pattern() const { | ||
static Pattern pattern = | ||
Pattern::create(PlanNode::Kind::kFilter, {Pattern::create(PlanNode::Kind::kAppendVertices)}); | ||
return pattern; | ||
} | ||
|
||
StatusOr<OptRule::TransformResult> PushFilterThroughAppendVerticesRule::transform( | ||
OptContext* octx, const MatchedResult& matched) const { | ||
auto* oldFilterGroupNode = matched.node; | ||
auto* oldFilterGroup = oldFilterGroupNode->group(); | ||
auto* oldFilterNode = static_cast<graph::Filter*>(oldFilterGroupNode->node()); | ||
auto* condition = oldFilterNode->condition(); | ||
auto* oldAvGroupNode = matched.dependencies[0].node; | ||
auto* oldAvNode = static_cast<graph::AppendVertices*>(oldAvGroupNode->node()); | ||
auto& dstNode = oldAvNode->nodeAlias(); | ||
|
||
auto inputColNames = oldAvNode->inputVars().front()->colNames; | ||
auto qctx = octx->qctx(); | ||
|
||
auto picker = [&inputColNames, &dstNode](const Expression* expr) -> bool { | ||
auto finder = [&inputColNames, &dstNode](const Expression* e) -> bool { | ||
if (e->isPropertyExpr() && | ||
std::find(inputColNames.begin(), | ||
inputColNames.end(), | ||
(static_cast<const PropertyExpression*>(e)->prop())) == inputColNames.end()) { | ||
return true; | ||
} | ||
if (e->kind() == Expression::Kind::kVar && | ||
static_cast<const VariableExpression*>(e)->var() == dstNode) { | ||
return true; | ||
} | ||
return false; | ||
}; | ||
graph::FindVisitor visitor(finder); | ||
const_cast<Expression*>(expr)->accept(&visitor); | ||
return visitor.results().empty(); | ||
}; | ||
Expression* filterPicked = nullptr; | ||
Expression* filterUnpicked = nullptr; | ||
graph::ExpressionUtils::splitFilter(condition, picker, &filterPicked, &filterUnpicked); | ||
|
||
if (!filterPicked) { | ||
return TransformResult::noTransform(); | ||
} | ||
|
||
// produce new Filter node below | ||
auto* newBelowFilterNode = | ||
graph::Filter::make(qctx, const_cast<graph::PlanNode*>(oldAvNode->dep()), filterPicked); | ||
newBelowFilterNode->setInputVar(oldAvNode->inputVar()); | ||
newBelowFilterNode->setColNames(oldAvNode->inputVars().front()->colNames); | ||
auto newBelowFilterGroup = OptGroup::create(octx); | ||
auto newFilterGroupNode = newBelowFilterGroup->makeGroupNode(newBelowFilterNode); | ||
newFilterGroupNode->setDeps(oldAvGroupNode->dependencies()); | ||
|
||
// produce new AppendVertices node | ||
auto* newAvNode = static_cast<graph::AppendVertices*>(oldAvNode->clone()); | ||
newAvNode->setInputVar(newBelowFilterNode->outputVar()); | ||
|
||
TransformResult result; | ||
result.eraseAll = true; | ||
if (filterUnpicked) { | ||
// produce new Filter node above | ||
auto* newAboveFilterNode = graph::Filter::make(octx->qctx(), newAvNode, filterUnpicked); | ||
newAboveFilterNode->setOutputVar(oldFilterNode->outputVar()); | ||
auto newAboveFilterGroupNode = OptGroupNode::create(octx, newAboveFilterNode, oldFilterGroup); | ||
|
||
auto newAvGroup = OptGroup::create(octx); | ||
auto newAvGroupNode = newAvGroup->makeGroupNode(newAvNode); | ||
newAvGroupNode->setDeps({newBelowFilterGroup}); | ||
newAvNode->setInputVar(newBelowFilterNode->outputVar()); | ||
newAboveFilterGroupNode->setDeps({newAvGroup}); | ||
newAboveFilterNode->setInputVar(newAvNode->outputVar()); | ||
result.newGroupNodes.emplace_back(newAboveFilterGroupNode); | ||
} else { | ||
newAvNode->setOutputVar(oldFilterNode->outputVar()); | ||
// newAvNode's col names, on the hand, should inherit those of the oldAvNode | ||
// since they are the same project. | ||
newAvNode->setColNames(oldAvNode->outputVarPtr()->colNames); | ||
auto newAvGroupNode = OptGroupNode::create(octx, newAvNode, oldFilterGroup); | ||
newAvGroupNode->setDeps({newBelowFilterGroup}); | ||
newAvNode->setInputVar(newBelowFilterNode->outputVar()); | ||
result.newGroupNodes.emplace_back(newAvGroupNode); | ||
} | ||
return result; | ||
} | ||
|
||
std::string PushFilterThroughAppendVerticesRule::toString() const { | ||
return "PushFilterThroughAppendVerticesRule"; | ||
} | ||
|
||
} // namespace opt | ||
} // namespace nebula |
46 changes: 46 additions & 0 deletions
46
src/graph/optimizer/rule/PushFilterThroughAppendVerticesRule.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
/* Copyright (c) 2023 vesoft inc. All rights reserved. | ||
* | ||
* This source code is licensed under Apache 2.0 License. | ||
*/ | ||
|
||
#ifndef GRAPH_OPTIMIZER_RULE_PUSHFILTERTHROUGHAPPENDVERTICES_H_ | ||
#define GRAPH_OPTIMIZER_RULE_PUSHFILTERTHROUGHAPPENDVERTICES_H_ | ||
|
||
#include "graph/optimizer/OptRule.h" | ||
|
||
namespace nebula { | ||
namespace opt { | ||
|
||
/* | ||
* Before: | ||
* Filter(e.likeness > 78 and v.prop > 40) | ||
* | | ||
* AppendVertices(v) | ||
* | ||
* After : | ||
* Filter(v.prop > 40) | ||
* | | ||
* AppendVertices(v) | ||
* | | ||
* Filter(e.likeness > 78) | ||
* | ||
*/ | ||
|
||
class PushFilterThroughAppendVerticesRule final : public OptRule { | ||
public: | ||
const Pattern &pattern() const override; | ||
|
||
StatusOr<TransformResult> transform(OptContext *ctx, const MatchedResult &matched) const override; | ||
|
||
std::string toString() const override; | ||
|
||
private: | ||
PushFilterThroughAppendVerticesRule(); | ||
|
||
static std::unique_ptr<OptRule> kInstance; | ||
}; | ||
|
||
} // namespace opt | ||
} // namespace nebula | ||
|
||
#endif // GRAPH_OPTIMIZER_RULE_PUSHFILTERTHROUGHAPPENDVERTICES_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.