Improve MERGE performance by using indices (#213)

This commit is contained in:
antonio2368 2021-08-30 11:39:06 +02:00 committed by GitHub
parent 0138d277d4
commit 5a8bda2531
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 32 additions and 4 deletions

View File

@ -291,16 +291,17 @@ can serve as inputs to others and thus a sequence of operations is formed.")
cpp<#) cpp<#)
(lcp:define-class once (logical-operator) (lcp:define-class once (logical-operator)
() ((symbols "std::vector<Symbol>" :scope :public))
(:documentation (:documentation
"A logical operator whose Cursor returns true on the first Pull "A logical operator whose Cursor returns true on the first Pull
and false on every following Pull.") and false on every following Pull.")
(:public (:public
#>cpp #>cpp
Once(std::vector<Symbol> symbols = {}) : symbols_{std::move(symbols)} {}
DEFVISITABLE(HierarchicalLogicalOperatorVisitor); DEFVISITABLE(HierarchicalLogicalOperatorVisitor);
UniqueCursorPtr MakeCursor(utils::MemoryResource *) const override; UniqueCursorPtr MakeCursor(utils::MemoryResource *) const override;
std::vector<Symbol> ModifiedSymbols(const SymbolTable &) const override { std::vector<Symbol> ModifiedSymbols(const SymbolTable &) const override {
return {}; return symbols_;
} }
bool HasSingleInput() const override; bool HasSingleInput() const override;

View File

@ -482,9 +482,16 @@ class RuleBasedPlanner {
// version when generating the create part. // version when generating the create part.
std::unordered_set<Symbol> bound_symbols_copy(context_->bound_symbols); std::unordered_set<Symbol> bound_symbols_copy(context_->bound_symbols);
MatchContext match_ctx{matching, *context_->symbol_table, bound_symbols_copy, storage::View::NEW}; MatchContext match_ctx{matching, *context_->symbol_table, bound_symbols_copy, storage::View::NEW};
auto on_match = PlanMatching(match_ctx, nullptr);
std::vector<Symbol> bound_symbols(context_->bound_symbols.begin(), context_->bound_symbols.end());
auto once_with_symbols = std::make_unique<Once>(bound_symbols);
auto on_match = PlanMatching(match_ctx, std::move(once_with_symbols));
once_with_symbols = std::make_unique<Once>(std::move(bound_symbols));
// Use the original bound_symbols, so we fill it with new symbols. // Use the original bound_symbols, so we fill it with new symbols.
auto on_create = GenCreateForPattern(*merge.pattern_, nullptr, *context_->symbol_table, context_->bound_symbols); auto on_create = GenCreateForPattern(*merge.pattern_, std::move(once_with_symbols), *context_->symbol_table,
context_->bound_symbols);
for (auto &set : merge.on_create_) { for (auto &set : merge.on_create_) {
on_create = HandleWriteClause(set, on_create, *context_->symbol_table, context_->bound_symbols); on_create = HandleWriteClause(set, on_create, *context_->symbol_table, context_->bound_symbols);
MG_ASSERT(on_create, "Expected SET in MERGE ... ON CREATE"); MG_ASSERT(on_create, "Expected SET in MERGE ... ON CREATE");

View File

@ -774,6 +774,26 @@ TYPED_TEST(TestPlanner, UnwindMergeNodeProperty) {
DeleteListContent(&on_create); DeleteListContent(&on_create);
} }
TYPED_TEST(TestPlanner, UnwindMergeNodePropertyWithIndex) {
// Test UNWIND [1] AS i MERGE (n :label {prop: i}) with label-property index
AstStorage storage;
FakeDbAccessor dba;
const auto label_name = "label";
const auto label = dba.Label(label_name);
const auto property = PROPERTY_PAIR("prop");
dba.SetIndexCount(label, property.second, 1);
auto node_n = NODE("n", label_name);
node_n->properties_[storage.GetPropertyIx(property.first)] = IDENT("i");
auto *query = QUERY(SINGLE_QUERY(UNWIND(LIST(LITERAL(1)), AS("i")), MERGE(PATTERN(node_n))));
std::list<BaseOpChecker *> on_match{new ExpectScanAllByLabelPropertyValue(label, property, IDENT("i"))};
std::list<BaseOpChecker *> on_create{new ExpectCreateNode()};
auto symbol_table = query::MakeSymbolTable(query);
auto planner = MakePlanner<TypeParam>(&dba, storage, symbol_table, query);
CheckPlan(planner.plan(), symbol_table, ExpectUnwind(), ExpectMerge(on_match, on_create));
DeleteListContent(&on_match);
DeleteListContent(&on_create);
}
TYPED_TEST(TestPlanner, MultipleOptionalMatchReturn) { TYPED_TEST(TestPlanner, MultipleOptionalMatchReturn) {
// Test OPTIONAL MATCH (n) OPTIONAL MATCH (m) RETURN n // Test OPTIONAL MATCH (n) OPTIONAL MATCH (m) RETURN n
AstStorage storage; AstStorage storage;