Add limiting number of generated plans for a query
Reviewers: florijan, mislav.bradac Reviewed By: mislav.bradac Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D548
This commit is contained in:
parent
d66d9e3b40
commit
99e27cb7e9
@ -1,5 +1,16 @@
|
|||||||
#include "query/plan/planner.hpp"
|
#include "query/plan/planner.hpp"
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
#include <gflags/gflags.h>
|
||||||
|
#include <glog/logging.h>
|
||||||
|
|
||||||
|
#include "utils/flag_validation.hpp"
|
||||||
|
|
||||||
|
DEFINE_VALIDATED_uint64(
|
||||||
|
query_max_plans, 1000U, "Maximum number of generated plans for a query",
|
||||||
|
FLAG_IN_RANGE(1, std::numeric_limits<std::uint64_t>::max()));
|
||||||
|
|
||||||
namespace query::plan {
|
namespace query::plan {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -153,6 +164,37 @@ std::vector<std::vector<T>> CartesianProduct(
|
|||||||
return products;
|
return products;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::uint64_t CartesianProductSize(const std::vector<std::vector<T>> &sets) {
|
||||||
|
std::uint64_t n = 1U;
|
||||||
|
for (const auto &set : sets) {
|
||||||
|
if (set.empty()) {
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
std::uint64_t new_n = n * set.size();
|
||||||
|
if (new_n < n || new_n < set.size()) {
|
||||||
|
DLOG(WARNING) << "Unsigned wrap-around when calculating expected size of "
|
||||||
|
"Cartesian product.";
|
||||||
|
return std::numeric_limits<std::uint64_t>::max();
|
||||||
|
}
|
||||||
|
n = new_n;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shortens variants if their Cartesian product exceeds the query_max_plans
|
||||||
|
// flag.
|
||||||
|
template <typename T>
|
||||||
|
void LimitPlans(std::vector<std::vector<T>> &variants) {
|
||||||
|
size_t to_shorten = 0U;
|
||||||
|
while (CartesianProductSize(variants) > FLAGS_query_max_plans) {
|
||||||
|
if (variants[to_shorten].size() > 1U) {
|
||||||
|
variants[to_shorten].pop_back();
|
||||||
|
}
|
||||||
|
to_shorten = (to_shorten + 1U) % variants.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Similar to VaryMatchingStart, but varies the starting nodes for all given
|
// Similar to VaryMatchingStart, but varies the starting nodes for all given
|
||||||
// matchings. After all matchings produce multiple alternative starts, the
|
// matchings. After all matchings produce multiple alternative starts, the
|
||||||
// Cartesian product of all of them is returned.
|
// Cartesian product of all of them is returned.
|
||||||
@ -162,6 +204,7 @@ std::vector<std::vector<Matching>> VaryMultiMatchingStarts(
|
|||||||
for (const auto &matching : matchings) {
|
for (const auto &matching : matchings) {
|
||||||
variants.emplace_back(VaryMatchingStart(matching, symbol_table));
|
variants.emplace_back(VaryMatchingStart(matching, symbol_table));
|
||||||
}
|
}
|
||||||
|
LimitPlans(variants);
|
||||||
return CartesianProduct<Matching>(variants.cbegin(), variants.cend());
|
return CartesianProduct<Matching>(variants.cbegin(), variants.cend());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,6 +275,7 @@ std::vector<std::vector<QueryPart>> VaryQueryMatching(
|
|||||||
alternative_query_parts.emplace_back(
|
alternative_query_parts.emplace_back(
|
||||||
VaryQuertPartMatching(query_part, symbol_table));
|
VaryQuertPartMatching(query_part, symbol_table));
|
||||||
}
|
}
|
||||||
|
LimitPlans(alternative_query_parts);
|
||||||
return CartesianProduct<QueryPart>(alternative_query_parts.cbegin(),
|
return CartesianProduct<QueryPart>(alternative_query_parts.cbegin(),
|
||||||
alternative_query_parts.cend());
|
alternative_query_parts.cend());
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user