Address PR comments
This commit is contained in:
@@ -445,13 +445,13 @@ class DbAccessor final {
|
||||
|
||||
std::vector<storage::LabelId> ClearLabelIndexStats() { return accessor_->ClearLabelIndexStats(); }
|
||||
|
||||
std::vector<std::pair<storage::LabelId, storage::PropertyId>> DeleteIndexStatsForLabels(
|
||||
std::vector<std::pair<storage::LabelId, storage::PropertyId>> DeleteLabelPropertyIndexStats(
|
||||
const std::span<std::string> labels) {
|
||||
return accessor_->DeleteIndexStatsForLabels(labels);
|
||||
return accessor_->DeleteLabelPropertyIndexStats(labels);
|
||||
}
|
||||
|
||||
std::vector<storage::LabelId> DeleteLabelIndexStatsForLabels(const std::span<std::string> labels) {
|
||||
return accessor_->DeleteLabelIndexStatsForLabels(labels);
|
||||
std::vector<storage::LabelId> DeleteLabelIndexStats(const std::span<std::string> labels) {
|
||||
return accessor_->DeleteLabelIndexStats(labels);
|
||||
}
|
||||
|
||||
void SetIndexStats(const storage::LabelId &label, const storage::LabelIndexStats &stats) {
|
||||
|
||||
@@ -167,10 +167,11 @@ bool SymbolGenerator::PreVisit(SingleQuery &) {
|
||||
// Union
|
||||
|
||||
bool SymbolGenerator::PreVisit(CypherUnion &) {
|
||||
auto scope = scopes_.back();
|
||||
scopes_.back() = Scope();
|
||||
auto next_scope = Scope();
|
||||
next_scope.curr_return_names = scopes_.back().curr_return_names;
|
||||
|
||||
scopes_.back().curr_return_names = scope.curr_return_names;
|
||||
scopes_.pop_back();
|
||||
scopes_.push_back(next_scope);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
#include "spdlog/spdlog.h"
|
||||
#include "storage/v2/edge.hpp"
|
||||
#include "storage/v2/id_types.hpp"
|
||||
#include "storage/v2/indices.hpp"
|
||||
#include "storage/v2/isolation_level.hpp"
|
||||
#include "storage/v2/property_value.hpp"
|
||||
#include "storage/v2/storage_mode.hpp"
|
||||
@@ -1526,91 +1525,110 @@ std::vector<std::vector<TypedValue>> AnalyzeGraphQueryHandler::AnalyzeGraphCreat
|
||||
std::map<LPIndex, uint64_t> vertex_degree_counter;
|
||||
auto view = storage::View::OLD;
|
||||
|
||||
// Preprocess labels in label indexes to avoid later checks
|
||||
auto erase_not_specified_label_indices = [&labels, execution_db_accessor](auto &index_info) {
|
||||
if (labels[0] != kAsterisk) {
|
||||
for (auto it = index_info.cbegin(); it != index_info.cend();) {
|
||||
if (std::find(labels.begin(), labels.end(), execution_db_accessor->LabelToName(*it)) == labels.end()) {
|
||||
it = index_info.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto erase_not_specified_label_property_indices = [&labels, execution_db_accessor](auto &index_info) {
|
||||
if (labels[0] != kAsterisk) {
|
||||
for (auto it = index_info.cbegin(); it != index_info.cend();) {
|
||||
if (std::find(labels.begin(), labels.end(), execution_db_accessor->LabelToName(it->first)) == labels.end()) {
|
||||
it = index_info.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto populate_label_stats = [execution_db_accessor, view](auto index_info) {
|
||||
std::vector<std::pair<storage::LabelId, storage::LabelIndexStats>> label_stats;
|
||||
label_stats.reserve(index_info.size());
|
||||
std::for_each(index_info.begin(), index_info.end(),
|
||||
[execution_db_accessor, view, &label_stats](const storage::LabelId &label_id) {
|
||||
auto vertices = execution_db_accessor->Vertices(view, label_id);
|
||||
uint64_t no_vertices{0};
|
||||
uint64_t total_degree{0};
|
||||
std::for_each(vertices.begin(), vertices.end(),
|
||||
[&total_degree, &no_vertices, &view](const auto &vertex) {
|
||||
no_vertices++;
|
||||
total_degree += *vertex.OutDegree(view) + *vertex.InDegree(view);
|
||||
});
|
||||
|
||||
auto average_degree =
|
||||
no_vertices > 0 ? static_cast<double>(total_degree) / static_cast<double>(no_vertices) : 0;
|
||||
auto index_stats = storage::LabelIndexStats{.count = no_vertices, .avg_degree = average_degree};
|
||||
execution_db_accessor->SetIndexStats(label_id, index_stats);
|
||||
label_stats.emplace_back(std::make_pair(label_id, index_stats));
|
||||
});
|
||||
|
||||
return label_stats;
|
||||
};
|
||||
|
||||
auto populate_label_property_stats = [&label_property_counter, &vertex_degree_counter, execution_db_accessor,
|
||||
view](auto &index_info) {
|
||||
// Iterate over all label property indexed vertices
|
||||
std::for_each(
|
||||
index_info.begin(), index_info.end(),
|
||||
[execution_db_accessor, &label_property_counter, &vertex_degree_counter, view](const LPIndex &index_info) {
|
||||
auto vertices = execution_db_accessor->Vertices(view, index_info.first, index_info.second);
|
||||
std::for_each(vertices.begin(), vertices.end(),
|
||||
[&index_info, &label_property_counter, &vertex_degree_counter, &view](const auto &vertex) {
|
||||
label_property_counter[index_info][*vertex.GetProperty(view, index_info.second)]++;
|
||||
vertex_degree_counter[index_info] += *vertex.OutDegree(view) + *vertex.InDegree(view);
|
||||
});
|
||||
});
|
||||
|
||||
std::vector<std::pair<LPIndex, storage::LabelPropertyIndexStats>> label_property_stats;
|
||||
label_property_stats.reserve(label_property_counter.size());
|
||||
std::for_each(
|
||||
label_property_counter.begin(), label_property_counter.end(),
|
||||
[execution_db_accessor, &vertex_degree_counter, &label_property_stats](const auto &counter_entry) {
|
||||
const auto &[label_property, values_map] = counter_entry;
|
||||
// Extract info
|
||||
uint64_t count_property_value = std::accumulate(
|
||||
values_map.begin(), values_map.end(), 0,
|
||||
[](uint64_t prev_value, const auto &prop_value_count) { return prev_value + prop_value_count.second; });
|
||||
// num_distinc_values will never be 0
|
||||
double avg_group_size = static_cast<double>(count_property_value) / static_cast<double>(values_map.size());
|
||||
double chi_squared_stat = std::accumulate(
|
||||
values_map.begin(), values_map.end(), 0.0, [avg_group_size](double prev_result, const auto &value_entry) {
|
||||
return prev_result + utils::ChiSquaredValue(value_entry.second, avg_group_size);
|
||||
});
|
||||
|
||||
double average_degree = count_property_value > 0
|
||||
? static_cast<double>(vertex_degree_counter[label_property]) /
|
||||
static_cast<double>(count_property_value)
|
||||
: 0;
|
||||
|
||||
auto index_stats =
|
||||
storage::LabelPropertyIndexStats{.count = count_property_value,
|
||||
.distinct_values_count = static_cast<uint64_t>(values_map.size()),
|
||||
.statistic = chi_squared_stat,
|
||||
.avg_group_size = avg_group_size,
|
||||
.avg_degree = average_degree};
|
||||
execution_db_accessor->SetIndexStats(label_property.first, label_property.second, index_stats);
|
||||
label_property_stats.push_back(std::make_pair(label_property, index_stats));
|
||||
});
|
||||
|
||||
return label_property_stats;
|
||||
};
|
||||
|
||||
std::vector<storage::LabelId> label_indices_info = execution_db_accessor->ListAllIndices().label;
|
||||
if (labels[0] != kAsterisk) {
|
||||
for (auto it = label_indices_info.cbegin(); it != label_indices_info.cend();) {
|
||||
if (std::find(labels.begin(), labels.end(), execution_db_accessor->LabelToName(*it)) == labels.end()) {
|
||||
it = label_indices_info.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
erase_not_specified_label_indices(label_indices_info);
|
||||
auto label_stats = populate_label_stats(label_indices_info);
|
||||
|
||||
// Preprocess labels in label property indexes to avoid later checks
|
||||
std::vector<LPIndex> label_property_indices_info = execution_db_accessor->ListAllIndices().label_property;
|
||||
if (labels[0] != kAsterisk) {
|
||||
for (auto it = label_property_indices_info.cbegin(); it != label_property_indices_info.cend();) {
|
||||
if (std::find(labels.begin(), labels.end(), execution_db_accessor->LabelToName(it->first)) == labels.end()) {
|
||||
it = label_property_indices_info.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::pair<storage::LabelId, storage::LabelIndexStats>> label_stats;
|
||||
// Iterate over all label indexed vertices
|
||||
std::for_each(label_indices_info.begin(), label_indices_info.end(),
|
||||
[execution_db_accessor, view, &label_stats](const storage::LabelId &index_info) {
|
||||
auto vertices = execution_db_accessor->Vertices(storage::View::OLD, index_info);
|
||||
int64_t no_vertices = 0;
|
||||
auto total_degree = 0;
|
||||
std::for_each(vertices.begin(), vertices.end(),
|
||||
[&total_degree, &no_vertices, &view](const auto &vertex) {
|
||||
no_vertices++;
|
||||
total_degree += *vertex.OutDegree(view) + *vertex.InDegree(view);
|
||||
});
|
||||
|
||||
auto average_degree =
|
||||
no_vertices > 0 ? static_cast<double>(total_degree) / static_cast<double>(no_vertices) : 0;
|
||||
auto index_stats = storage::LabelIndexStats{.count = no_vertices, .avg_degree = average_degree};
|
||||
execution_db_accessor->SetIndexStats(index_info, index_stats);
|
||||
label_stats.emplace_back(std::make_pair(index_info, index_stats));
|
||||
});
|
||||
|
||||
// Iterate over all label property indexed vertices
|
||||
std::for_each(
|
||||
label_property_indices_info.begin(), label_property_indices_info.end(),
|
||||
[execution_db_accessor, &label_property_counter, &vertex_degree_counter, view](const LPIndex &index_info) {
|
||||
auto vertices = execution_db_accessor->Vertices(view, index_info.first, index_info.second);
|
||||
std::for_each(vertices.begin(), vertices.end(),
|
||||
[&index_info, &label_property_counter, &vertex_degree_counter, &view](const auto &vertex) {
|
||||
label_property_counter[index_info][*vertex.GetProperty(view, index_info.second)]++;
|
||||
vertex_degree_counter[index_info] += *vertex.OutDegree(view) + *vertex.InDegree(view);
|
||||
});
|
||||
});
|
||||
|
||||
std::vector<std::pair<LPIndex, storage::LabelPropertyIndexStats>> label_property_stats;
|
||||
std::for_each(
|
||||
label_property_counter.begin(), label_property_counter.end(),
|
||||
[execution_db_accessor, &vertex_degree_counter, &label_property_stats](const auto &counter_entry) {
|
||||
const auto &[label_property, values_map] = counter_entry;
|
||||
// Extract info
|
||||
int64_t count_property_value = std::accumulate(
|
||||
values_map.begin(), values_map.end(), 0,
|
||||
[](int64_t prev_value, const auto &prop_value_count) { return prev_value + prop_value_count.second; });
|
||||
// num_distinc_values will never be 0
|
||||
double avg_group_size = static_cast<double>(count_property_value) / static_cast<double>(values_map.size());
|
||||
double chi_squared_stat = std::accumulate(
|
||||
values_map.begin(), values_map.end(), 0.0, [avg_group_size](double prev_result, const auto &value_entry) {
|
||||
return prev_result + utils::ChiSquaredValue(value_entry.second, avg_group_size);
|
||||
});
|
||||
|
||||
double average_degree = count_property_value > 0 ? static_cast<double>(vertex_degree_counter[label_property]) /
|
||||
static_cast<double>(count_property_value)
|
||||
: 0;
|
||||
|
||||
auto index_stats =
|
||||
storage::LabelPropertyIndexStats{.count = count_property_value,
|
||||
.distinct_values_count = static_cast<int64_t>(values_map.size()),
|
||||
.statistic = chi_squared_stat,
|
||||
.avg_group_size = avg_group_size,
|
||||
.avg_degree = average_degree};
|
||||
execution_db_accessor->SetIndexStats(label_property.first, label_property.second, index_stats);
|
||||
label_property_stats.push_back(std::make_pair(label_property, index_stats));
|
||||
});
|
||||
erase_not_specified_label_property_indices(label_property_indices_info);
|
||||
auto label_property_stats = populate_label_property_stats(label_property_indices_info);
|
||||
|
||||
std::vector<std::vector<TypedValue>> results;
|
||||
results.reserve(label_stats.size() + label_property_stats.size());
|
||||
@@ -1621,7 +1639,7 @@ std::vector<std::vector<TypedValue>> AnalyzeGraphQueryHandler::AnalyzeGraphCreat
|
||||
|
||||
result.emplace_back(execution_db_accessor->LabelToName(stat_entry.first));
|
||||
result.emplace_back(TypedValue());
|
||||
result.emplace_back(stat_entry.second.count);
|
||||
result.emplace_back(static_cast<int64_t>(stat_entry.second.count));
|
||||
result.emplace_back(TypedValue());
|
||||
result.emplace_back(TypedValue());
|
||||
result.emplace_back(TypedValue());
|
||||
@@ -1636,8 +1654,8 @@ std::vector<std::vector<TypedValue>> AnalyzeGraphQueryHandler::AnalyzeGraphCreat
|
||||
|
||||
result.emplace_back(execution_db_accessor->LabelToName(stat_entry.first.first));
|
||||
result.emplace_back(execution_db_accessor->PropertyToName(stat_entry.first.second));
|
||||
result.emplace_back(stat_entry.second.count);
|
||||
result.emplace_back(stat_entry.second.distinct_values_count);
|
||||
result.emplace_back(static_cast<int64_t>(stat_entry.second.count));
|
||||
result.emplace_back(static_cast<int64_t>(stat_entry.second.distinct_values_count));
|
||||
result.emplace_back(stat_entry.second.avg_group_size);
|
||||
result.emplace_back(stat_entry.second.statistic);
|
||||
result.emplace_back(stat_entry.second.avg_degree);
|
||||
@@ -1655,11 +1673,12 @@ std::vector<std::vector<TypedValue>> AnalyzeGraphQueryHandler::AnalyzeGraphDelet
|
||||
label_prop_results = execution_db_accessor->ClearLabelPropertyIndexStats();
|
||||
label_results = execution_db_accessor->ClearLabelIndexStats();
|
||||
} else {
|
||||
label_prop_results = execution_db_accessor->DeleteIndexStatsForLabels(labels);
|
||||
label_results = execution_db_accessor->DeleteLabelIndexStatsForLabels(labels);
|
||||
label_prop_results = execution_db_accessor->DeleteLabelPropertyIndexStats(labels);
|
||||
label_results = execution_db_accessor->DeleteLabelIndexStats(labels);
|
||||
}
|
||||
|
||||
std::vector<std::vector<TypedValue>> results;
|
||||
results.reserve(label_prop_results.size() + label_results.size());
|
||||
std::transform(label_prop_results.begin(), label_prop_results.end(), std::back_inserter(results),
|
||||
[execution_db_accessor](const auto &label_property_index) {
|
||||
return std::vector<TypedValue>{
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "query/plan/operator.hpp"
|
||||
#include "query/typed_value.hpp"
|
||||
#include "utils/algorithm.hpp"
|
||||
#include "utils/math.hpp"
|
||||
|
||||
namespace memgraph::query::plan {
|
||||
|
||||
@@ -25,7 +26,7 @@ namespace memgraph::query::plan {
|
||||
* how to do expands and other types of Cypher manipulations.
|
||||
*/
|
||||
struct SymbolStatistics {
|
||||
int64_t cardinality;
|
||||
uint64_t count;
|
||||
double degree;
|
||||
};
|
||||
|
||||
@@ -288,11 +289,11 @@ class CostEstimator : public HierarchicalLogicalOperatorVisitor {
|
||||
auto stats = GetStatsFor(symbol);
|
||||
if (stats.has_value()) {
|
||||
scope.symbol_stats[symbol.name()] =
|
||||
SymbolStatistics{.cardinality = stats.value().cardinality, .degree = stats.value().degree};
|
||||
SymbolStatistics{.count = stats.value().count, .degree = stats.value().degree};
|
||||
}
|
||||
}
|
||||
|
||||
scopes_.push_back(scope);
|
||||
scopes_.push_back(std::move(scope));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -301,9 +302,9 @@ class CostEstimator : public HierarchicalLogicalOperatorVisitor {
|
||||
op.input_->Accept(*this);
|
||||
|
||||
// Estimate cost on the subquery branch independently, use a copy
|
||||
auto last_scope = scopes_.back();
|
||||
auto &last_scope = scopes_.back();
|
||||
double subquery_cost = EstimateCostOnBranch(&op.subquery_, last_scope);
|
||||
subquery_cost = subquery_cost != 0 ? subquery_cost : 1;
|
||||
subquery_cost = !utils::ApproxEqualDecimal(subquery_cost, 0.0) ? subquery_cost : 1;
|
||||
cardinality_ *= subquery_cost;
|
||||
|
||||
IncrementCost(CostParam::kSubquery);
|
||||
@@ -387,12 +388,10 @@ class CostEstimator : public HierarchicalLogicalOperatorVisitor {
|
||||
template <typename T>
|
||||
void SaveStatsFor(const Symbol &symbol, T index_stats) {
|
||||
scopes_.back().symbol_stats[symbol.name()] = SymbolStatistics{
|
||||
.cardinality = index_stats.count,
|
||||
.count = index_stats.count,
|
||||
.degree = index_stats.avg_degree,
|
||||
};
|
||||
}
|
||||
|
||||
void DeleteStatsFor(const Symbol &symbol) { scopes_.back().symbol_stats.erase(symbol.name()); }
|
||||
};
|
||||
|
||||
/** Returns the estimated cost of the given plan. */
|
||||
|
||||
@@ -498,7 +498,7 @@ std::vector<LabelId> LabelIndex::ClearIndexStats() {
|
||||
return deleted_indexes;
|
||||
}
|
||||
|
||||
std::vector<LabelId> LabelIndex::DeleteIndexStatsForLabel(const storage::LabelId &label) {
|
||||
std::vector<LabelId> LabelIndex::DeleteIndexStats(const storage::LabelId &label) {
|
||||
std::vector<LabelId> deleted_indexes;
|
||||
for (auto it = stats_.cbegin(); it != stats_.cend();) {
|
||||
if (it->first == label) {
|
||||
@@ -848,8 +848,7 @@ int64_t LabelPropertyIndex::ApproximateVertexCount(LabelId label, PropertyId pro
|
||||
/*
|
||||
Iterate over all property-label pairs and deletes if label from the index is equal to label parameter.
|
||||
*/
|
||||
std::vector<std::pair<LabelId, PropertyId>> LabelPropertyIndex::DeleteIndexStatsForLabel(
|
||||
const storage::LabelId &label) {
|
||||
std::vector<std::pair<LabelId, PropertyId>> LabelPropertyIndex::DeleteIndexStats(const storage::LabelId &label) {
|
||||
std::vector<std::pair<LabelId, PropertyId>> deleted_indexes;
|
||||
for (auto it = stats_.cbegin(); it != stats_.cend();) {
|
||||
if (it->first.first == label) {
|
||||
@@ -871,14 +870,14 @@ std::vector<std::pair<LabelId, PropertyId>> LabelPropertyIndex::ClearIndexStats(
|
||||
return deleted_indexes;
|
||||
}
|
||||
|
||||
void LabelPropertyIndex::SetIndexStats(const storage::LabelId &label, const storage::PropertyId &property,
|
||||
void LabelPropertyIndex::SetIndexStats(const std::pair<storage::LabelId, storage::PropertyId> &key,
|
||||
const storage::LabelPropertyIndexStats &stats) {
|
||||
stats_[{label, property}] = stats;
|
||||
stats_[key] = stats;
|
||||
}
|
||||
|
||||
std::optional<storage::LabelPropertyIndexStats> LabelPropertyIndex::GetIndexStats(
|
||||
const storage::LabelId &label, const storage::PropertyId &property) const {
|
||||
if (auto it = stats_.find({label, property}); it != stats_.end()) {
|
||||
const std::pair<storage::LabelId, storage::PropertyId> &key) const {
|
||||
if (auto it = stats_.find(key); it != stats_.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return {};
|
||||
|
||||
@@ -32,7 +32,7 @@ using ParalellizedIndexCreationInfo =
|
||||
std::pair<std::vector<std::pair<Gid, uint64_t>> /*vertex_recovery_info*/, uint64_t /*thread_count*/>;
|
||||
|
||||
struct LabelIndexStats {
|
||||
int64_t count;
|
||||
uint64_t count;
|
||||
double avg_degree;
|
||||
};
|
||||
|
||||
@@ -135,7 +135,7 @@ class LabelIndex {
|
||||
|
||||
std::vector<LabelId> ClearIndexStats();
|
||||
|
||||
std::vector<LabelId> DeleteIndexStatsForLabel(const storage::LabelId &label);
|
||||
std::vector<LabelId> DeleteIndexStats(const storage::LabelId &label);
|
||||
|
||||
void Clear() { index_.clear(); }
|
||||
|
||||
@@ -150,7 +150,7 @@ class LabelIndex {
|
||||
};
|
||||
|
||||
struct LabelPropertyIndexStats {
|
||||
int64_t count, distinct_values_count;
|
||||
uint64_t count, distinct_values_count;
|
||||
double statistic, avg_group_size, avg_degree;
|
||||
};
|
||||
|
||||
@@ -263,13 +263,13 @@ class LabelPropertyIndex {
|
||||
|
||||
std::vector<std::pair<LabelId, PropertyId>> ClearIndexStats();
|
||||
|
||||
std::vector<std::pair<LabelId, PropertyId>> DeleteIndexStatsForLabel(const storage::LabelId &label);
|
||||
std::vector<std::pair<LabelId, PropertyId>> DeleteIndexStats(const storage::LabelId &label);
|
||||
|
||||
void SetIndexStats(const storage::LabelId &label, const storage::PropertyId &property,
|
||||
void SetIndexStats(const std::pair<storage::LabelId, storage::PropertyId> &key,
|
||||
const storage::LabelPropertyIndexStats &stats);
|
||||
|
||||
std::optional<storage::LabelPropertyIndexStats> GetIndexStats(const storage::LabelId &label,
|
||||
const storage::PropertyId &property) const;
|
||||
std::optional<storage::LabelPropertyIndexStats> GetIndexStats(
|
||||
const std::pair<storage::LabelId, storage::PropertyId> &key) const;
|
||||
|
||||
void Clear() { index_.clear(); }
|
||||
|
||||
|
||||
@@ -267,51 +267,66 @@ class Storage final {
|
||||
return storage_->indices_.label_property_index.ApproximateVertexCount(label, property, lower, upper);
|
||||
}
|
||||
|
||||
template <typename TResult, typename TIndex, typename TIndexKey>
|
||||
std::optional<TResult> GetIndexStatsForIndex(TIndex &index, TIndexKey &&key) const {
|
||||
return index.GetIndexStats(key);
|
||||
}
|
||||
|
||||
std::optional<storage::LabelIndexStats> GetIndexStats(const storage::LabelId &label) const {
|
||||
return storage_->indices_.label_index.GetIndexStats(label);
|
||||
return GetIndexStatsForIndex<storage::LabelIndexStats>(storage_->indices_.label_index, label);
|
||||
}
|
||||
|
||||
std::optional<storage::LabelPropertyIndexStats> GetIndexStats(const storage::LabelId &label,
|
||||
const storage::PropertyId &property) const {
|
||||
return storage_->indices_.label_property_index.GetIndexStats(label, property);
|
||||
return GetIndexStatsForIndex<storage::LabelPropertyIndexStats>(storage_->indices_.label_property_index,
|
||||
std::make_pair(label, property));
|
||||
}
|
||||
|
||||
std::vector<std::pair<LabelId, PropertyId>> ClearLabelPropertyIndexStats() {
|
||||
return storage_->indices_.label_property_index.ClearIndexStats();
|
||||
}
|
||||
|
||||
std::vector<LabelId> ClearLabelIndexStats() { return storage_->indices_.label_index.ClearIndexStats(); }
|
||||
|
||||
std::vector<std::pair<LabelId, PropertyId>> DeleteIndexStatsForLabels(const std::span<std::string> labels) {
|
||||
std::vector<std::pair<LabelId, PropertyId>> deleted_indexes;
|
||||
std::for_each(labels.begin(), labels.end(), [this, &deleted_indexes](const auto &label_str) {
|
||||
std::vector<std::pair<LabelId, PropertyId>> loc_results =
|
||||
storage_->indices_.label_property_index.DeleteIndexStatsForLabel(NameToLabel(label_str));
|
||||
deleted_indexes.insert(deleted_indexes.end(), std::make_move_iterator(loc_results.begin()),
|
||||
std::make_move_iterator(loc_results.end()));
|
||||
});
|
||||
return deleted_indexes;
|
||||
}
|
||||
|
||||
std::vector<LabelId> DeleteLabelIndexStatsForLabels(const std::span<std::string> labels) {
|
||||
std::vector<LabelId> deleted_indexes;
|
||||
std::for_each(labels.begin(), labels.end(), [this, &deleted_indexes](const auto &label_str) {
|
||||
std::vector<LabelId> loc_results =
|
||||
storage_->indices_.label_index.DeleteIndexStatsForLabel(NameToLabel(label_str));
|
||||
deleted_indexes.insert(deleted_indexes.end(), std::make_move_iterator(loc_results.begin()),
|
||||
std::make_move_iterator(loc_results.end()));
|
||||
});
|
||||
|
||||
return deleted_indexes;
|
||||
template <typename TIndex, typename TIndexKey, typename TIndexStats>
|
||||
void SetIndexStatsForIndex(TIndex &index, TIndexKey &&key, TIndexStats &stats) const {
|
||||
index.SetIndexStats(key, stats);
|
||||
}
|
||||
|
||||
void SetIndexStats(const storage::LabelId &label, const LabelIndexStats &stats) {
|
||||
storage_->indices_.label_index.SetIndexStats(label, stats);
|
||||
SetIndexStatsForIndex(storage_->indices_.label_index, label, stats);
|
||||
}
|
||||
|
||||
void SetIndexStats(const storage::LabelId &label, const storage::PropertyId &property,
|
||||
const LabelPropertyIndexStats &stats) {
|
||||
storage_->indices_.label_property_index.SetIndexStats(label, property, stats);
|
||||
SetIndexStatsForIndex(storage_->indices_.label_property_index, std::make_pair(label, property), stats);
|
||||
}
|
||||
|
||||
template <typename TResult, typename TIndex>
|
||||
std::vector<TResult> ClearIndexStatsForIndex(TIndex &index) const {
|
||||
return index.ClearIndexStats();
|
||||
}
|
||||
|
||||
std::vector<std::pair<LabelId, PropertyId>> ClearLabelPropertyIndexStats() {
|
||||
return ClearIndexStatsForIndex<std::pair<LabelId, PropertyId>>(storage_->indices_.label_property_index);
|
||||
}
|
||||
|
||||
std::vector<LabelId> ClearLabelIndexStats() {
|
||||
return ClearIndexStatsForIndex<LabelId>(storage_->indices_.label_index);
|
||||
}
|
||||
|
||||
template <typename TResult, typename TIndex>
|
||||
std::vector<TResult> DeleteIndexStatsForIndex(TIndex &index, const std::span<std::string> labels) {
|
||||
std::vector<TResult> deleted_indexes;
|
||||
|
||||
for (const auto &label : labels) {
|
||||
std::vector<TResult> loc_results = index.DeleteIndexStats(NameToLabel(label));
|
||||
deleted_indexes.insert(deleted_indexes.end(), std::make_move_iterator(loc_results.begin()),
|
||||
std::make_move_iterator(loc_results.end()));
|
||||
}
|
||||
return deleted_indexes;
|
||||
}
|
||||
|
||||
std::vector<std::pair<LabelId, PropertyId>> DeleteLabelPropertyIndexStats(const std::span<std::string> labels) {
|
||||
return DeleteIndexStatsForIndex<std::pair<LabelId, PropertyId>>(storage_->indices_.label_property_index, labels);
|
||||
}
|
||||
|
||||
std::vector<LabelId> DeleteLabelIndexStats(const std::span<std::string> labels) {
|
||||
return DeleteIndexStatsForIndex<LabelId>(storage_->indices_.label_index, labels);
|
||||
}
|
||||
|
||||
/// @return Accessor to the deleted vertex if a deletion took place, std::nullopt otherwise
|
||||
|
||||
@@ -14,9 +14,7 @@ import sys
|
||||
import pytest
|
||||
from common import connect, execute_and_fetch_all, memgraph
|
||||
|
||||
|
||||
class OptimizeIndexesConstants:
|
||||
QUERY_PLAN = "QUERY PLAN"
|
||||
QUERY_PLAN = "QUERY PLAN"
|
||||
|
||||
|
||||
# E2E tests for checking query semantic
|
||||
@@ -308,7 +306,7 @@ def test_given_supernode_when_expanding_then_expand_other_way_around(memgraph):
|
||||
]
|
||||
|
||||
result_without_analysis = list(memgraph.execute_and_fetch(query))
|
||||
result_without_analysis = [x[OptimizeIndexesConstants.QUERY_PLAN] for x in result_without_analysis]
|
||||
result_without_analysis = [x[QUERY_PLAN] for x in result_without_analysis]
|
||||
assert expected_explain == result_without_analysis
|
||||
|
||||
memgraph.execute("analyze graph;")
|
||||
@@ -319,7 +317,7 @@ def test_given_supernode_when_expanding_then_expand_other_way_around(memgraph):
|
||||
]
|
||||
|
||||
result_with_analysis = list(memgraph.execute_and_fetch(query))
|
||||
result_with_analysis = [x[OptimizeIndexesConstants.QUERY_PLAN] for x in result_with_analysis]
|
||||
result_with_analysis = [x[QUERY_PLAN] for x in result_with_analysis]
|
||||
|
||||
assert expected_explain == result_with_analysis
|
||||
|
||||
@@ -363,7 +361,7 @@ def test_given_supernode_when_subquery_then_carry_information_to_subquery(memgra
|
||||
]
|
||||
|
||||
result_without_analysis = list(memgraph.execute_and_fetch(query))
|
||||
result_without_analysis = [x[OptimizeIndexesConstants.QUERY_PLAN] for x in result_without_analysis]
|
||||
result_without_analysis = [x[QUERY_PLAN] for x in result_without_analysis]
|
||||
assert expected_explain == result_without_analysis
|
||||
|
||||
memgraph.execute("analyze graph;")
|
||||
@@ -373,7 +371,7 @@ def test_given_supernode_when_subquery_then_carry_information_to_subquery(memgra
|
||||
for x in expected_explain
|
||||
]
|
||||
result_with_analysis = list(memgraph.execute_and_fetch(query))
|
||||
result_with_analysis = [x[OptimizeIndexesConstants.QUERY_PLAN] for x in result_with_analysis]
|
||||
result_with_analysis = [x[QUERY_PLAN] for x in result_with_analysis]
|
||||
|
||||
assert expected_explain == result_with_analysis
|
||||
|
||||
@@ -435,7 +433,7 @@ def test_given_supernode_when_subquery_and_union_then_carry_information(memgraph
|
||||
]
|
||||
|
||||
result_without_analysis = list(memgraph.execute_and_fetch(query))
|
||||
result_without_analysis = [x[OptimizeIndexesConstants.QUERY_PLAN] for x in result_without_analysis]
|
||||
result_without_analysis = [x[QUERY_PLAN] for x in result_without_analysis]
|
||||
assert expected_explain == result_without_analysis
|
||||
|
||||
memgraph.execute("analyze graph;")
|
||||
@@ -449,7 +447,7 @@ def test_given_supernode_when_subquery_and_union_then_carry_information(memgraph
|
||||
for x in expected_explain
|
||||
]
|
||||
result_with_analysis = list(memgraph.execute_and_fetch(query))
|
||||
result_with_analysis = [x[OptimizeIndexesConstants.QUERY_PLAN] for x in result_with_analysis]
|
||||
result_with_analysis = [x[QUERY_PLAN] for x in result_with_analysis]
|
||||
|
||||
assert expected_explain == result_with_analysis
|
||||
|
||||
|
||||
Reference in New Issue
Block a user