Add the possibility of primary-key based indexing
Add new possibility to base our indexing solution on. Add ScanAllOperator that represents the semantics and integrate its use through index_lookup.
This commit is contained in:
parent
5c0e41ed44
commit
814c5eb397
@ -92,6 +92,7 @@ extern const Event ScanAllByLabelPropertyRangeOperator;
|
|||||||
extern const Event ScanAllByLabelPropertyValueOperator;
|
extern const Event ScanAllByLabelPropertyValueOperator;
|
||||||
extern const Event ScanAllByLabelPropertyOperator;
|
extern const Event ScanAllByLabelPropertyOperator;
|
||||||
extern const Event ScanAllByIdOperator;
|
extern const Event ScanAllByIdOperator;
|
||||||
|
extern const Event ScanAllByPrimaryKeyOperator;
|
||||||
extern const Event ExpandOperator;
|
extern const Event ExpandOperator;
|
||||||
extern const Event ExpandVariableOperator;
|
extern const Event ExpandVariableOperator;
|
||||||
extern const Event ConstructNamedPathOperator;
|
extern const Event ConstructNamedPathOperator;
|
||||||
@ -545,6 +546,20 @@ UniqueCursorPtr ScanAllByLabelProperty::MakeCursor(utils::MemoryResource *mem) c
|
|||||||
throw QueryRuntimeException("ScanAllByLabelProperty is not supported");
|
throw QueryRuntimeException("ScanAllByLabelProperty is not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ScanAllByPrimaryKey::ScanAllByPrimaryKey(const std::shared_ptr<LogicalOperator> &input, Symbol output_symbol,
|
||||||
|
storage::v3::LabelId label, std::vector<query::v2::Expression *> primary_key,
|
||||||
|
storage::v3::View view)
|
||||||
|
: ScanAll(input, output_symbol, view), label_(label), primary_key_(primary_key) {
|
||||||
|
MG_ASSERT(primary_key.front());
|
||||||
|
}
|
||||||
|
|
||||||
|
ACCEPT_WITH_INPUT(ScanAllByPrimaryKey)
|
||||||
|
|
||||||
|
UniqueCursorPtr ScanAllByPrimaryKey::MakeCursor(utils::MemoryResource *mem) const {
|
||||||
|
// EventCounter::IncrementCounter(EventCounter::ScanAllByPrimaryKeyOperator);
|
||||||
|
throw QueryRuntimeException("ScanAllByPrimaryKey cursur is yet to be implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
ScanAllById::ScanAllById(const std::shared_ptr<LogicalOperator> &input, Symbol output_symbol, Expression *expression,
|
ScanAllById::ScanAllById(const std::shared_ptr<LogicalOperator> &input, Symbol output_symbol, Expression *expression,
|
||||||
storage::v3::View view)
|
storage::v3::View view)
|
||||||
: ScanAll(input, output_symbol, view), expression_(expression) {
|
: ScanAll(input, output_symbol, view), expression_(expression) {
|
||||||
|
@ -111,6 +111,7 @@ class ScanAllByLabelPropertyRange;
|
|||||||
class ScanAllByLabelPropertyValue;
|
class ScanAllByLabelPropertyValue;
|
||||||
class ScanAllByLabelProperty;
|
class ScanAllByLabelProperty;
|
||||||
class ScanAllById;
|
class ScanAllById;
|
||||||
|
class ScanAllByPrimaryKey;
|
||||||
class Expand;
|
class Expand;
|
||||||
class ExpandVariable;
|
class ExpandVariable;
|
||||||
class ConstructNamedPath;
|
class ConstructNamedPath;
|
||||||
@ -141,7 +142,7 @@ class Foreach;
|
|||||||
using LogicalOperatorCompositeVisitor = utils::CompositeVisitor<
|
using LogicalOperatorCompositeVisitor = utils::CompositeVisitor<
|
||||||
Once, CreateNode, CreateExpand, ScanAll, ScanAllByLabel,
|
Once, CreateNode, CreateExpand, ScanAll, ScanAllByLabel,
|
||||||
ScanAllByLabelPropertyRange, ScanAllByLabelPropertyValue,
|
ScanAllByLabelPropertyRange, ScanAllByLabelPropertyValue,
|
||||||
ScanAllByLabelProperty, ScanAllById,
|
ScanAllByLabelProperty, ScanAllById, ScanAllByPrimaryKey,
|
||||||
Expand, ExpandVariable, ConstructNamedPath, Filter, Produce, Delete,
|
Expand, ExpandVariable, ConstructNamedPath, Filter, Produce, Delete,
|
||||||
SetProperty, SetProperties, SetLabels, RemoveProperty, RemoveLabels,
|
SetProperty, SetProperties, SetLabels, RemoveProperty, RemoveLabels,
|
||||||
EdgeUniquenessFilter, Accumulate, Aggregate, Skip, Limit, OrderBy, Merge,
|
EdgeUniquenessFilter, Accumulate, Aggregate, Skip, Limit, OrderBy, Merge,
|
||||||
@ -841,7 +842,28 @@ given label and property.
|
|||||||
(:serialize (:slk))
|
(:serialize (:slk))
|
||||||
(:clone))
|
(:clone))
|
||||||
|
|
||||||
|
(lcp:define-class scan-all-by-primary-key (scan-all)
|
||||||
|
((label "::storage::v3::LabelId" :scope :public)
|
||||||
|
(primary-key "std::vector<Expression*>" :scope :public)
|
||||||
|
(expression "Expression *" :scope :public
|
||||||
|
:slk-save #'slk-save-ast-pointer
|
||||||
|
:slk-load (slk-load-ast-pointer "Expression")))
|
||||||
|
(:documentation
|
||||||
|
"ScanAll producing a single node with specified by the label and primary key")
|
||||||
|
(:public
|
||||||
|
#>cpp
|
||||||
|
ScanAllByPrimaryKey() {}
|
||||||
|
ScanAllByPrimaryKey(const std::shared_ptr<LogicalOperator> &input,
|
||||||
|
Symbol output_symbol,
|
||||||
|
storage::v3::LabelId label,
|
||||||
|
std::vector<query::v2::Expression*> primary_key,
|
||||||
|
storage::v3::View view = storage::v3::View::OLD);
|
||||||
|
|
||||||
|
bool Accept(HierarchicalLogicalOperatorVisitor &visitor) override;
|
||||||
|
UniqueCursorPtr MakeCursor(utils::MemoryResource *) const override;
|
||||||
|
cpp<#)
|
||||||
|
(:serialize (:slk))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(lcp:define-class scan-all-by-id (scan-all)
|
(lcp:define-class scan-all-by-id (scan-all)
|
||||||
((expression "Expression *" :scope :public
|
((expression "Expression *" :scope :public
|
||||||
|
@ -25,8 +25,10 @@
|
|||||||
|
|
||||||
#include <gflags/gflags.h>
|
#include <gflags/gflags.h>
|
||||||
|
|
||||||
|
#include "query/v2/frontend/ast/ast.hpp"
|
||||||
#include "query/v2/plan/operator.hpp"
|
#include "query/v2/plan/operator.hpp"
|
||||||
#include "query/v2/plan/preprocess.hpp"
|
#include "query/v2/plan/preprocess.hpp"
|
||||||
|
#include "storage/v3/id_types.hpp"
|
||||||
|
|
||||||
DECLARE_int64(query_vertex_count_to_expand_existing);
|
DECLARE_int64(query_vertex_count_to_expand_existing);
|
||||||
|
|
||||||
@ -584,6 +586,26 @@ class IndexLookupRewriter final : public HierarchicalLogicalOperatorVisitor {
|
|||||||
// Without labels, we cannot generate any indexed ScanAll.
|
// Without labels, we cannot generate any indexed ScanAll.
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// First, try to see if we can find a vertex based on the possibly
|
||||||
|
// supplied primary key.
|
||||||
|
auto property_filters = filters_.PropertyFilters(node_symbol);
|
||||||
|
storage::v3::LabelId prim_label;
|
||||||
|
std::vector<query::v2::Expression *> primary_key;
|
||||||
|
|
||||||
|
if (!property_filters.empty()) {
|
||||||
|
for (const auto &label : labels) {
|
||||||
|
if (db_->LabelIndexExists(GetLabel(label))) {
|
||||||
|
prim_label = GetLabel(label);
|
||||||
|
primary_key = db_->ExtractPrimaryKey(prim_label, property_filters);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!primary_key.empty()) {
|
||||||
|
return std::make_unique<ScanAllByPrimaryKey>(input, node_symbol, prim_label, primary_key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto found_index = FindBestLabelPropertyIndex(node_symbol, bound_symbols);
|
auto found_index = FindBestLabelPropertyIndex(node_symbol, bound_symbols);
|
||||||
if (found_index &&
|
if (found_index &&
|
||||||
// Use label+property index if we satisfy max_vertex_count.
|
// Use label+property index if we satisfy max_vertex_count.
|
||||||
|
@ -12,9 +12,11 @@
|
|||||||
/// @file
|
/// @file
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <iterator>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
#include "query/v2/bindings/typed_value.hpp"
|
#include "query/v2/bindings/typed_value.hpp"
|
||||||
|
#include "query/v2/plan/preprocess.hpp"
|
||||||
#include "query/v2/shard_request_manager.hpp"
|
#include "query/v2/shard_request_manager.hpp"
|
||||||
#include "storage/v3/conversions.hpp"
|
#include "storage/v3/conversions.hpp"
|
||||||
#include "storage/v3/id_types.hpp"
|
#include "storage/v3/id_types.hpp"
|
||||||
@ -52,11 +54,31 @@ class VertexCountCache {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For now return true if label is primary label
|
|
||||||
bool LabelIndexExists(storage::v3::LabelId label) { return shard_request_manager_->IsPrimaryLabel(label); }
|
bool LabelIndexExists(storage::v3::LabelId label) { return shard_request_manager_->IsPrimaryLabel(label); }
|
||||||
|
|
||||||
bool LabelPropertyIndexExists(storage::v3::LabelId /*label*/, storage::v3::PropertyId /*property*/) { return false; }
|
bool LabelPropertyIndexExists(storage::v3::LabelId /*label*/, storage::v3::PropertyId /*property*/) { return false; }
|
||||||
|
|
||||||
|
std::vector<query::v2::Expression *> ExtractPrimaryKey(storage::v3::LabelId label,
|
||||||
|
std::vector<query::v2::plan::FilterInfo> property_filters) {
|
||||||
|
std::vector<query::v2::Expression *> pk;
|
||||||
|
const auto schema = shard_request_manager_->GetSchemaForLabel(label);
|
||||||
|
|
||||||
|
std::vector<storage::v3::PropertyId> schema_properties;
|
||||||
|
schema_properties.reserve(schema.size());
|
||||||
|
|
||||||
|
std::transform(schema.begin(), schema.end(), std::back_inserter(schema_properties),
|
||||||
|
[](const auto &schema_elem) { return schema_elem.property_id; });
|
||||||
|
|
||||||
|
for (const auto &property_filter : property_filters) {
|
||||||
|
const auto &property_id = NameToProperty(property_filter.property_filter->property_.name);
|
||||||
|
if (std::find(schema_properties.begin(), schema_properties.end(), property_id) != schema_properties.end()) {
|
||||||
|
pk.push_back(property_filter.expression);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pk.size() == schema_properties.size() ? pk : std::vector<query::v2::Expression *>{};
|
||||||
|
}
|
||||||
|
|
||||||
msgs::ShardRequestManagerInterface *shard_request_manager_;
|
msgs::ShardRequestManagerInterface *shard_request_manager_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -131,6 +131,7 @@ class ShardRequestManagerInterface {
|
|||||||
virtual const std::string &EdgeTypeToName(memgraph::storage::v3::EdgeTypeId type) const = 0;
|
virtual const std::string &EdgeTypeToName(memgraph::storage::v3::EdgeTypeId type) const = 0;
|
||||||
virtual bool IsPrimaryLabel(LabelId label) const = 0;
|
virtual bool IsPrimaryLabel(LabelId label) const = 0;
|
||||||
virtual bool IsPrimaryKey(LabelId primary_label, PropertyId property) const = 0;
|
virtual bool IsPrimaryKey(LabelId primary_label, PropertyId property) const = 0;
|
||||||
|
virtual std::vector<coordinator::SchemaProperty> GetSchemaForLabel(LabelId label) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO(kostasrim)rename this class template
|
// TODO(kostasrim)rename this class template
|
||||||
@ -244,6 +245,10 @@ class ShardRequestManager : public ShardRequestManagerInterface {
|
|||||||
}) != schema_it->second.end();
|
}) != schema_it->second.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<coordinator::SchemaProperty> GetSchemaForLabel(LabelId label) const override {
|
||||||
|
return shards_map_.schemas.at(label);
|
||||||
|
}
|
||||||
|
|
||||||
bool IsPrimaryLabel(LabelId label) const override { return shards_map_.label_spaces.contains(label); }
|
bool IsPrimaryLabel(LabelId label) const override { return shards_map_.label_spaces.contains(label); }
|
||||||
|
|
||||||
// TODO(kostasrim) Simplify return result
|
// TODO(kostasrim) Simplify return result
|
||||||
|
Loading…
Reference in New Issue
Block a user