Enhance planner for edge-id indexing
This commit is contained in:
parent
956705293e
commit
a5ee0fad08
@ -48,11 +48,26 @@ class EdgeTypeIndexRewriter final : public HierarchicalLogicalOperatorVisitor {
|
||||
|
||||
bool PreVisit(Filter &op) override {
|
||||
prev_ops_.push_back(&op);
|
||||
filters_.CollectFilterExpression(op.expression_, *symbol_table_);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PostVisit(Filter & /*op*/) override {
|
||||
bool PostVisit(Filter &op) override {
|
||||
prev_ops_.pop_back();
|
||||
|
||||
ExpressionRemovalResult removal = RemoveExpressions(op.expression_, filter_exprs_for_removal_);
|
||||
op.expression_ = removal.trimmed_expression;
|
||||
if (op.expression_) {
|
||||
Filters leftover_filters;
|
||||
leftover_filters.CollectFilterExpression(op.expression_, *symbol_table_);
|
||||
op.all_filters_ = std::move(leftover_filters);
|
||||
}
|
||||
|
||||
if (!op.expression_) {
|
||||
SetOnParent(op.input());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -70,7 +85,7 @@ class EdgeTypeIndexRewriter final : public HierarchicalLogicalOperatorVisitor {
|
||||
bool PostVisit(ScanAll &op) override {
|
||||
prev_ops_.pop_back();
|
||||
|
||||
if (EdgeTypeIndexingPossible()) {
|
||||
if (EdgeTypeIndexingPossible() || maybe_id_lookup_value_) {
|
||||
SetOnParent(op.input());
|
||||
}
|
||||
|
||||
@ -88,6 +103,25 @@ class EdgeTypeIndexRewriter final : public HierarchicalLogicalOperatorVisitor {
|
||||
edge_type_index_exist = only_one_edge_type ? db_->EdgeTypeIndexExists(op.common_.edge_types.front()) : false;
|
||||
|
||||
scanall_under_expand_ = only_one_edge_type && expansion_is_named && expdanded_node_not_named;
|
||||
|
||||
const auto &output_symbol = op.common_.edge_symbol;
|
||||
const auto &modified_symbols = op.ModifiedSymbols(*symbol_table_);
|
||||
std::unordered_set<Symbol> bound_symbols(modified_symbols.begin(), modified_symbols.end());
|
||||
auto are_bound = [&bound_symbols](const auto &used_symbols) {
|
||||
for (const auto &used_symbol : used_symbols) {
|
||||
if (!utils::Contains(bound_symbols, used_symbol)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
for (const auto &filter : filters_.IdFilters(output_symbol)) {
|
||||
if (filter.id_filter->is_symbol_in_value_ || !are_bound(filter.used_symbols)) continue;
|
||||
maybe_id_lookup_value_ = filter.id_filter->value_;
|
||||
filter_exprs_for_removal_.insert(filter.expression);
|
||||
filters_.EraseFilter(filter);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -96,9 +130,10 @@ class EdgeTypeIndexRewriter final : public HierarchicalLogicalOperatorVisitor {
|
||||
bool PostVisit(Expand &op) override {
|
||||
prev_ops_.pop_back();
|
||||
|
||||
if (EdgeTypeIndexingPossible()) {
|
||||
if (EdgeTypeIndexingPossible() || maybe_id_lookup_value_) {
|
||||
auto indexed_scan = GenEdgeTypeScan(op);
|
||||
SetOnParent(std::move(indexed_scan));
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -488,9 +523,12 @@ class EdgeTypeIndexRewriter final : public HierarchicalLogicalOperatorVisitor {
|
||||
std::vector<LogicalOperator *> prev_ops_;
|
||||
std::unordered_set<Symbol> cartesian_symbols_;
|
||||
|
||||
memgraph::query::Expression *maybe_id_lookup_value_ = nullptr;
|
||||
|
||||
bool EdgeTypeIndexingPossible() const {
|
||||
return expand_under_produce_ && scanall_under_expand_ && once_under_scanall_ && edge_type_index_exist;
|
||||
}
|
||||
|
||||
bool expand_under_produce_ = false;
|
||||
bool scanall_under_expand_ = false;
|
||||
bool once_under_scanall_ = false;
|
||||
@ -500,14 +538,21 @@ class EdgeTypeIndexRewriter final : public HierarchicalLogicalOperatorVisitor {
|
||||
throw utils::NotYetImplemented("Operator not yet covered by EdgeTypeIndexRewriter");
|
||||
}
|
||||
|
||||
std::unique_ptr<ScanAllByEdgeType> GenEdgeTypeScan(const Expand &expand) {
|
||||
std::unique_ptr<ScanAll> GenEdgeTypeScan(const Expand &expand) {
|
||||
const auto &input = expand.input();
|
||||
const auto &output_symbol = expand.common_.edge_symbol;
|
||||
const auto &view = expand.view_;
|
||||
|
||||
// Extract edge_type from symbol
|
||||
auto edge_type = expand.common_.edge_types.front();
|
||||
return std::make_unique<ScanAllByEdgeType>(input, output_symbol, edge_type, view);
|
||||
if (EdgeTypeIndexingPossible()) {
|
||||
auto edge_type = expand.common_.edge_types.front();
|
||||
return std::make_unique<ScanAllByEdgeType>(input, output_symbol, edge_type, view);
|
||||
}
|
||||
|
||||
if (maybe_id_lookup_value_) {
|
||||
return std::make_unique<ScanAllByEdgeId>(input, output_symbol, maybe_id_lookup_value_, view);
|
||||
}
|
||||
|
||||
LOG_FATAL("Fatal error while rewriting query plan.");
|
||||
}
|
||||
|
||||
void SetOnParent(const std::shared_ptr<LogicalOperator> &input) {
|
||||
|
@ -29,7 +29,9 @@ namespace memgraph::storage {
|
||||
std::optional<EdgeAccessor> EdgeAccessor::Create(EdgeRef edge, EdgeTypeId edge_type, Vertex *from_vertex,
|
||||
Vertex *to_vertex, Storage *storage, Transaction *transaction,
|
||||
bool for_deleted) {
|
||||
return std::nullopt;
|
||||
// TODO Take the view as well and determine if the
|
||||
// constructs are visible or not. Checkout VertexAccessor.
|
||||
return EdgeAccessor(edge, edge_type, from_vertex, to_vertex, storage, transaction, for_deleted);
|
||||
}
|
||||
|
||||
bool EdgeAccessor::IsDeleted() const {
|
||||
|
@ -1429,16 +1429,24 @@ EdgesIterable InMemoryStorage::InMemoryAccessor::Edges(EdgeTypeId edge_type, Vie
|
||||
std::optional<EdgeAccessor> InMemoryStorage::InMemoryAccessor::FindEdge(Gid gid, View view) {
|
||||
auto *mem_storage = static_cast<InMemoryStorage *>(storage_);
|
||||
|
||||
auto edge_acc = mem_storage->edges_.access();
|
||||
auto edge_it = edge_acc.find(gid);
|
||||
if (edge_it == edge_acc.end()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
auto *edge_ptr = &(*edge_it);
|
||||
|
||||
// TODO replace this logic once we have a proper edge struct in place.
|
||||
// This should be only temporary, currently we have to do this whole
|
||||
// lookup through all the vertices, since the edge struct only has a
|
||||
// pointer to it's GID, it has no information whatsoever about the from
|
||||
// and to vertices.
|
||||
auto acc = mem_storage->vertices_.access();
|
||||
|
||||
auto maybe_edge_info = std::invoke([&]() -> std::optional<std::tuple<EdgeRef, EdgeTypeId, Vertex *, Vertex *>> {
|
||||
for (auto &vertex : acc) {
|
||||
for (auto &edge : vertex.out_edges) {
|
||||
if (std::get<2>(edge).gid == gid) {
|
||||
if (std::get<2>(edge).ptr == edge_ptr) {
|
||||
return std::make_tuple(std::get<2>(edge), std::get<0>(edge), &vertex, std::get<1>(edge));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user