mirror of https://gitee.com/bigwinds/arangodb
make "parallelize-gather" an optimizer rule, so it can be turned off
This commit is contained in:
parent
407d9dcd49
commit
791c926327
|
@ -63,7 +63,28 @@ namespace {
|
||||||
arangodb::velocypack::StringRef const SortModeUnset("unset");
|
arangodb::velocypack::StringRef const SortModeUnset("unset");
|
||||||
arangodb::velocypack::StringRef const SortModeMinElement("minelement");
|
arangodb::velocypack::StringRef const SortModeMinElement("minelement");
|
||||||
arangodb::velocypack::StringRef const SortModeHeap("heap");
|
arangodb::velocypack::StringRef const SortModeHeap("heap");
|
||||||
|
|
||||||
|
char const* toString(GatherNode::Parallelism value) {
|
||||||
|
switch (value) {
|
||||||
|
case GatherNode::Parallelism::Parallel:
|
||||||
|
return "parallel";
|
||||||
|
case GatherNode::Parallelism::Serial:
|
||||||
|
return "serial";
|
||||||
|
case GatherNode::Parallelism::Undefined:
|
||||||
|
default:
|
||||||
|
return "undefined";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GatherNode::Parallelism parallelismFromString(std::string const& value) {
|
||||||
|
if (value == "parallel") {
|
||||||
|
return GatherNode::Parallelism::Parallel;
|
||||||
|
} else if (value == "serial") {
|
||||||
|
return GatherNode::Parallelism::Serial;
|
||||||
|
}
|
||||||
|
return GatherNode::Parallelism::Undefined;
|
||||||
|
}
|
||||||
|
|
||||||
std::map<arangodb::velocypack::StringRef, GatherNode::SortMode> const NameToValue{
|
std::map<arangodb::velocypack::StringRef, GatherNode::SortMode> const NameToValue{
|
||||||
{SortModeMinElement, GatherNode::SortMode::MinElement},
|
{SortModeMinElement, GatherNode::SortMode::MinElement},
|
||||||
{SortModeHeap, GatherNode::SortMode::Heap},
|
{SortModeHeap, GatherNode::SortMode::Heap},
|
||||||
|
@ -400,6 +421,7 @@ GatherNode::GatherNode(ExecutionPlan* plan, arangodb::velocypack::Slice const& b
|
||||||
: ExecutionNode(plan, base),
|
: ExecutionNode(plan, base),
|
||||||
_elements(elements),
|
_elements(elements),
|
||||||
_sortmode(SortMode::MinElement),
|
_sortmode(SortMode::MinElement),
|
||||||
|
_parallelism(Parallelism::Undefined),
|
||||||
_limit(0) {
|
_limit(0) {
|
||||||
if (!_elements.empty()) {
|
if (!_elements.empty()) {
|
||||||
auto const sortModeSlice = base.get("sortmode");
|
auto const sortModeSlice = base.get("sortmode");
|
||||||
|
@ -414,16 +436,23 @@ GatherNode::GatherNode(ExecutionPlan* plan, arangodb::velocypack::Slice const& b
|
||||||
basics::VelocyPackHelper::getNumericValue<decltype(_limit)>(base,
|
basics::VelocyPackHelper::getNumericValue<decltype(_limit)>(base,
|
||||||
"limit", 0);
|
"limit", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setParallelism(parallelismFromString(VelocyPackHelper::getStringValue(base, "parellelism", "")));
|
||||||
}
|
}
|
||||||
|
|
||||||
GatherNode::GatherNode(ExecutionPlan* plan, size_t id, SortMode sortMode) noexcept
|
GatherNode::GatherNode(ExecutionPlan* plan, size_t id, SortMode sortMode, Parallelism parallelism) noexcept
|
||||||
: ExecutionNode(plan, id), _sortmode(sortMode), _limit(0) {}
|
: ExecutionNode(plan, id),
|
||||||
|
_sortmode(sortMode),
|
||||||
|
_parallelism(parallelism),
|
||||||
|
_limit(0) {}
|
||||||
|
|
||||||
/// @brief toVelocyPack, for GatherNode
|
/// @brief toVelocyPack, for GatherNode
|
||||||
void GatherNode::toVelocyPackHelper(VPackBuilder& nodes, unsigned flags,
|
void GatherNode::toVelocyPackHelper(VPackBuilder& nodes, unsigned flags,
|
||||||
std::unordered_set<ExecutionNode const*>& seen) const {
|
std::unordered_set<ExecutionNode const*>& seen) const {
|
||||||
// call base class method
|
// call base class method
|
||||||
ExecutionNode::toVelocyPackHelperGeneric(nodes, flags, seen);
|
ExecutionNode::toVelocyPackHelperGeneric(nodes, flags, seen);
|
||||||
|
|
||||||
|
nodes.add("parallelism", VPackValue(toString(_parallelism)));
|
||||||
|
|
||||||
if (_elements.empty()) {
|
if (_elements.empty()) {
|
||||||
nodes.add("sortmode", VPackValue(SortModeUnset.data()));
|
nodes.add("sortmode", VPackValue(SortModeUnset.data()));
|
||||||
|
@ -450,8 +479,6 @@ void GatherNode::toVelocyPackHelper(VPackBuilder& nodes, unsigned flags,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nodes.add("isParallelizable", VPackValue(isParallelizable()));
|
|
||||||
|
|
||||||
// And close it:
|
// And close it:
|
||||||
nodes.close();
|
nodes.close();
|
||||||
}
|
}
|
||||||
|
@ -467,7 +494,7 @@ std::unique_ptr<ExecutionBlock> GatherNode::createBlock(
|
||||||
|
|
||||||
if (ServerState::instance()->isCoordinator()) {
|
if (ServerState::instance()->isCoordinator()) {
|
||||||
// In the coordinator case the GatherBlock will fetch from RemoteBlocks.
|
// In the coordinator case the GatherBlock will fetch from RemoteBlocks.
|
||||||
if (isParallelizable()) {
|
if (_parallelism == Parallelism::Parallel) {
|
||||||
UnsortedGatherExecutorInfos infos(getRegisterPlan()->nrRegs[getDepth()],
|
UnsortedGatherExecutorInfos infos(getRegisterPlan()->nrRegs[getDepth()],
|
||||||
calcRegsToKeep(), getRegsToClear());
|
calcRegsToKeep(), getRegsToClear());
|
||||||
return std::make_unique<ExecutionBlockImpl<UnsortedGatherExecutor>>(&engine, this, std::move(infos));
|
return std::make_unique<ExecutionBlockImpl<UnsortedGatherExecutor>>(&engine, this, std::move(infos));
|
||||||
|
@ -542,7 +569,15 @@ struct ParallelizableFinder final : public WalkerWorker<ExecutionNode> {
|
||||||
};
|
};
|
||||||
|
|
||||||
/// no modification nodes, ScatterNodes etc
|
/// no modification nodes, ScatterNodes etc
|
||||||
bool GatherNode::isParallelizable() const noexcept {
|
bool GatherNode::isParallelizable() const {
|
||||||
|
if (_parallelism == Parallelism::Serial) {
|
||||||
|
// node already defined to be serial
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isInSubquery()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
ParallelizableFinder finder;
|
ParallelizableFinder finder;
|
||||||
for (ExecutionNode* e : _dependencies) {
|
for (ExecutionNode* e : _dependencies) {
|
||||||
e->walk(finder);
|
e->walk(finder);
|
||||||
|
@ -553,6 +588,11 @@ bool GatherNode::isParallelizable() const noexcept {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GatherNode::setParallelism(GatherNode::Parallelism value) {
|
||||||
|
TRI_ASSERT(value != Parallelism::Parallel || isParallelizable());
|
||||||
|
_parallelism = value;
|
||||||
|
}
|
||||||
|
|
||||||
SingleRemoteOperationNode::SingleRemoteOperationNode(
|
SingleRemoteOperationNode::SingleRemoteOperationNode(
|
||||||
ExecutionPlan* plan, size_t id, NodeType mode, bool replaceIndexNode,
|
ExecutionPlan* plan, size_t id, NodeType mode, bool replaceIndexNode,
|
||||||
std::string const& key, Collection const* collection,
|
std::string const& key, Collection const* collection,
|
||||||
|
|
|
@ -288,6 +288,8 @@ class GatherNode final : public ExecutionNode {
|
||||||
public:
|
public:
|
||||||
enum class SortMode : uint32_t { MinElement, Heap, Default };
|
enum class SortMode : uint32_t { MinElement, Heap, Default };
|
||||||
|
|
||||||
|
enum class Parallelism : uint32_t { Undefined, Parallel, Serial };
|
||||||
|
|
||||||
/// @brief inspect dependencies starting from a specified 'node'
|
/// @brief inspect dependencies starting from a specified 'node'
|
||||||
/// and return first corresponding collection within
|
/// and return first corresponding collection within
|
||||||
/// a diamond if so exist
|
/// a diamond if so exist
|
||||||
|
@ -301,7 +303,8 @@ class GatherNode final : public ExecutionNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief constructor with an id
|
/// @brief constructor with an id
|
||||||
GatherNode(ExecutionPlan* plan, size_t id, SortMode sortMode) noexcept;
|
GatherNode(ExecutionPlan* plan, size_t id, SortMode sortMode,
|
||||||
|
Parallelism parallelism = Parallelism::Undefined) noexcept;
|
||||||
|
|
||||||
GatherNode(ExecutionPlan*, arangodb::velocypack::Slice const& base,
|
GatherNode(ExecutionPlan*, arangodb::velocypack::Slice const& base,
|
||||||
SortElementVector const& elements);
|
SortElementVector const& elements);
|
||||||
|
@ -316,7 +319,7 @@ class GatherNode final : public ExecutionNode {
|
||||||
/// @brief clone ExecutionNode recursively
|
/// @brief clone ExecutionNode recursively
|
||||||
ExecutionNode* clone(ExecutionPlan* plan, bool withDependencies,
|
ExecutionNode* clone(ExecutionPlan* plan, bool withDependencies,
|
||||||
bool withProperties) const override final {
|
bool withProperties) const override final {
|
||||||
auto other = std::make_unique<GatherNode>(plan, _id, _sortmode);
|
auto other = std::make_unique<GatherNode>(plan, _id, _sortmode, _parallelism);
|
||||||
other->setConstrainedSortLimit(constrainedSortLimit());
|
other->setConstrainedSortLimit(constrainedSortLimit());
|
||||||
return cloneHelper(std::move(other), withDependencies, withProperties);
|
return cloneHelper(std::move(other), withDependencies, withProperties);
|
||||||
}
|
}
|
||||||
|
@ -351,8 +354,10 @@ class GatherNode final : public ExecutionNode {
|
||||||
|
|
||||||
bool isSortingGather() const noexcept;
|
bool isSortingGather() const noexcept;
|
||||||
|
|
||||||
|
void setParallelism(Parallelism value);
|
||||||
|
|
||||||
/// no modification nodes, ScatterNodes etc
|
/// no modification nodes, ScatterNodes etc
|
||||||
bool isParallelizable() const noexcept;
|
bool isParallelizable() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// @brief sort elements, variable, ascending flags and possible attribute
|
/// @brief sort elements, variable, ascending flags and possible attribute
|
||||||
|
@ -361,6 +366,9 @@ class GatherNode final : public ExecutionNode {
|
||||||
|
|
||||||
/// @brief sorting mode
|
/// @brief sorting mode
|
||||||
SortMode _sortmode;
|
SortMode _sortmode;
|
||||||
|
|
||||||
|
/// @brief parallelism
|
||||||
|
Parallelism _parallelism;
|
||||||
|
|
||||||
/// @brief In case this was created from a constrained heap sorting node, this
|
/// @brief In case this was created from a constrained heap sorting node, this
|
||||||
/// is its limit (which is greater than zero). Otherwise, it's zero.
|
/// is its limit (which is greater than zero). Otherwise, it's zero.
|
||||||
|
|
|
@ -116,26 +116,6 @@ std::unordered_map<int, std::string const> const typeNames{
|
||||||
"DistributeConsumer"},
|
"DistributeConsumer"},
|
||||||
{static_cast<int>(ExecutionNode::MATERIALIZE),
|
{static_cast<int>(ExecutionNode::MATERIALIZE),
|
||||||
"MaterializeNode"}};
|
"MaterializeNode"}};
|
||||||
|
|
||||||
// FIXME -- this temporary function should be
|
|
||||||
// replaced by a ExecutionNode member variable
|
|
||||||
// that shows the subquery depth and if filled
|
|
||||||
// during register planning
|
|
||||||
bool isInSubQuery(ExecutionNode const* node) {
|
|
||||||
auto current = node;
|
|
||||||
TRI_ASSERT(current != nullptr);
|
|
||||||
while (current != nullptr && current->hasDependency()) {
|
|
||||||
current = current->getFirstDependency();
|
|
||||||
}
|
|
||||||
if (ADB_UNLIKELY(current == nullptr)) {
|
|
||||||
// shouldn't happen in reality, just to please the compiler
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
TRI_ASSERT(current != nullptr);
|
|
||||||
TRI_ASSERT(current->getType() == ExecutionNode::NodeType::SINGLETON);
|
|
||||||
return current->id() != 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
/// @brief resolve nodeType to a string.
|
/// @brief resolve nodeType to a string.
|
||||||
|
@ -163,6 +143,15 @@ void ExecutionNode::validateType(int type) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ExecutionNode::isInSubquery() const {
|
||||||
|
auto const* current = this;
|
||||||
|
while (current != nullptr && current->hasDependency()) {
|
||||||
|
current = current->getFirstDependency();
|
||||||
|
}
|
||||||
|
TRI_ASSERT(current != nullptr);
|
||||||
|
return current->id() != 1;
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief add a dependency
|
/// @brief add a dependency
|
||||||
void ExecutionNode::addDependency(ExecutionNode* ep) {
|
void ExecutionNode::addDependency(ExecutionNode* ep) {
|
||||||
TRI_ASSERT(ep != nullptr);
|
TRI_ASSERT(ep != nullptr);
|
||||||
|
@ -1209,7 +1198,7 @@ std::unique_ptr<ExecutionBlock> SingletonNode::createBlock(
|
||||||
RegisterId const nrRegs = getRegisterPlan()->nrRegs[getDepth()];
|
RegisterId const nrRegs = getRegisterPlan()->nrRegs[getDepth()];
|
||||||
|
|
||||||
std::unordered_set<RegisterId> toKeep;
|
std::unordered_set<RegisterId> toKeep;
|
||||||
if (::isInSubQuery(this)) {
|
if (isInSubquery()) {
|
||||||
for (auto const& var : this->getVarsUsedLater()) {
|
for (auto const& var : this->getVarsUsedLater()) {
|
||||||
auto val = variableToRegisterId(var);
|
auto val = variableToRegisterId(var);
|
||||||
if (val < nrRegs) {
|
if (val < nrRegs) {
|
||||||
|
@ -1481,7 +1470,7 @@ std::unique_ptr<ExecutionBlock> LimitNode::createBlock(
|
||||||
TRI_ASSERT(previousNode != nullptr);
|
TRI_ASSERT(previousNode != nullptr);
|
||||||
|
|
||||||
// Fullcount must only be enabled on the last limit node on the main level
|
// Fullcount must only be enabled on the last limit node on the main level
|
||||||
TRI_ASSERT(!_fullCount || !::isInSubQuery(this));
|
TRI_ASSERT(!_fullCount || !isInSubquery());
|
||||||
|
|
||||||
LimitExecutorInfos infos(getRegisterPlan()->nrRegs[previousNode->getDepth()],
|
LimitExecutorInfos infos(getRegisterPlan()->nrRegs[previousNode->getDepth()],
|
||||||
getRegisterPlan()->nrRegs[getDepth()], getRegsToClear(),
|
getRegisterPlan()->nrRegs[getDepth()], getRegsToClear(),
|
||||||
|
|
|
@ -215,6 +215,9 @@ class ExecutionNode {
|
||||||
/// not.
|
/// not.
|
||||||
static void validateType(int type);
|
static void validateType(int type);
|
||||||
|
|
||||||
|
/// @brief whether or not a node is located inside a subquery
|
||||||
|
bool isInSubquery() const;
|
||||||
|
|
||||||
/// @brief add a dependency
|
/// @brief add a dependency
|
||||||
void addDependency(ExecutionNode*);
|
void addDependency(ExecutionNode*);
|
||||||
|
|
||||||
|
|
|
@ -294,7 +294,10 @@ struct OptimizerRule {
|
||||||
|
|
||||||
// moves filters on collection data into EnumerateCollection to
|
// moves filters on collection data into EnumerateCollection to
|
||||||
// avoid copying large amounts of unneeded documents
|
// avoid copying large amounts of unneeded documents
|
||||||
moveFiltersIntoEnumerateCollection,
|
moveFiltersIntoEnumerateCollectionRule,
|
||||||
|
|
||||||
|
// parallelizes execution in coordinator-sided GatherNodes
|
||||||
|
parallelizeGatherRule,
|
||||||
|
|
||||||
// move document materialization after SORT and LIMIT
|
// move document materialization after SORT and LIMIT
|
||||||
// this must be run AFTER all cluster rules as this rule
|
// this must be run AFTER all cluster rules as this rule
|
||||||
|
|
|
@ -3727,6 +3727,8 @@ void arangodb::aql::scatterInClusterRule(Optimizer* opt, std::unique_ptr<Executi
|
||||||
TRI_ASSERT(false);
|
TRI_ASSERT(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TRI_ASSERT(collection != nullptr);
|
||||||
|
|
||||||
// insert a scatter node
|
// insert a scatter node
|
||||||
auto* scatterNode =
|
auto* scatterNode =
|
||||||
new ScatterNode(plan.get(), plan->nextId(), ScatterNode::ScatterType::SHARD);
|
new ScatterNode(plan.get(), plan->nextId(), ScatterNode::ScatterType::SHARD);
|
||||||
|
@ -3752,7 +3754,10 @@ void arangodb::aql::scatterInClusterRule(Optimizer* opt, std::unique_ptr<Executi
|
||||||
|
|
||||||
// insert a gather node
|
// insert a gather node
|
||||||
auto const sortMode = GatherNode::evaluateSortMode(collection->numberOfShards());
|
auto const sortMode = GatherNode::evaluateSortMode(collection->numberOfShards());
|
||||||
auto* gatherNode = new GatherNode(plan.get(), plan->nextId(), sortMode);
|
// single-sharded collections don't require any parallelism. collections with more than
|
||||||
|
// one shard are eligible for later parallelization (the Undefined allows this)
|
||||||
|
auto const parallelism = (collection->numberOfShards() <= 1 ? GatherNode::Parallelism::Serial : GatherNode::Parallelism::Undefined);
|
||||||
|
auto* gatherNode = new GatherNode(plan.get(), plan->nextId(), sortMode, parallelism);
|
||||||
plan->registerNode(gatherNode);
|
plan->registerNode(gatherNode);
|
||||||
TRI_ASSERT(remoteNode);
|
TRI_ASSERT(remoteNode);
|
||||||
gatherNode->addDependency(remoteNode);
|
gatherNode->addDependency(remoteNode);
|
||||||
|
@ -3994,7 +3999,8 @@ void arangodb::aql::distributeInClusterRule(Optimizer* opt,
|
||||||
|
|
||||||
// insert a gather node
|
// insert a gather node
|
||||||
auto const sortMode = GatherNode::evaluateSortMode(collection->numberOfShards());
|
auto const sortMode = GatherNode::evaluateSortMode(collection->numberOfShards());
|
||||||
auto* gatherNode = new GatherNode(plan.get(), plan->nextId(), sortMode);
|
auto const parallelism = GatherNode::Parallelism::Undefined;
|
||||||
|
auto* gatherNode = new GatherNode(plan.get(), plan->nextId(), sortMode, parallelism);
|
||||||
plan->registerNode(gatherNode);
|
plan->registerNode(gatherNode);
|
||||||
gatherNode->addDependency(remoteNode);
|
gatherNode->addDependency(remoteNode);
|
||||||
|
|
||||||
|
@ -7274,6 +7280,28 @@ void arangodb::aql::moveFiltersIntoEnumerateRule(Optimizer* opt, std::unique_ptr
|
||||||
opt->addPlan(std::move(plan), rule, modified);
|
opt->addPlan(std::move(plan), rule, modified);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief parallelize coordinator GatherNodes
|
||||||
|
void arangodb::aql::parallelizeGatherRule(Optimizer* opt, std::unique_ptr<ExecutionPlan> plan,
|
||||||
|
OptimizerRule const& rule) {
|
||||||
|
TRI_ASSERT(ServerState::instance()->isCoordinator());
|
||||||
|
|
||||||
|
bool modified = false;
|
||||||
|
|
||||||
|
::arangodb::containers::SmallVector<ExecutionNode*>::allocator_type::arena_type a;
|
||||||
|
::arangodb::containers::SmallVector<ExecutionNode*> nodes{a};
|
||||||
|
plan->findNodesOfType(nodes, EN::GATHER, false);
|
||||||
|
|
||||||
|
for (auto const& n : nodes) {
|
||||||
|
GatherNode* gn = ExecutionNode::castTo<GatherNode*>(n);
|
||||||
|
if (gn->isParallelizable()) {
|
||||||
|
gn->setParallelism(GatherNode::Parallelism::Parallel);
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
opt->addPlan(std::move(plan), rule, modified);
|
||||||
|
}
|
||||||
|
|
||||||
// Splices in subqueries by replacing subquery nodes by
|
// Splices in subqueries by replacing subquery nodes by
|
||||||
// a SubqueryStartNode and a SubqueryEndNode with the subquery's nodes
|
// a SubqueryStartNode and a SubqueryEndNode with the subquery's nodes
|
||||||
// in between.
|
// in between.
|
||||||
|
|
|
@ -262,6 +262,9 @@ void replaceNearWithinFulltextRule(Optimizer*, std::unique_ptr<ExecutionPlan>,
|
||||||
void moveFiltersIntoEnumerateRule(Optimizer*, std::unique_ptr<ExecutionPlan>,
|
void moveFiltersIntoEnumerateRule(Optimizer*, std::unique_ptr<ExecutionPlan>,
|
||||||
OptimizerRule const&);
|
OptimizerRule const&);
|
||||||
|
|
||||||
|
/// @brief parallelize Gather nodes (cluster-only)
|
||||||
|
void parallelizeGatherRule(Optimizer*, std::unique_ptr<ExecutionPlan>, OptimizerRule const&);
|
||||||
|
|
||||||
//// @brief splice in subqueries
|
//// @brief splice in subqueries
|
||||||
void spliceSubqueriesRule(Optimizer*, std::unique_ptr<ExecutionPlan>, OptimizerRule const&);
|
void spliceSubqueriesRule(Optimizer*, std::unique_ptr<ExecutionPlan>, OptimizerRule const&);
|
||||||
|
|
||||||
|
|
|
@ -377,9 +377,22 @@ void OptimizerRulesFeature::addRules() {
|
||||||
OptimizerRule::Flags::ClusterOnly));
|
OptimizerRule::Flags::ClusterOnly));
|
||||||
|
|
||||||
registerRule("move-filters-into-enumerate", moveFiltersIntoEnumerateRule,
|
registerRule("move-filters-into-enumerate", moveFiltersIntoEnumerateRule,
|
||||||
OptimizerRule::moveFiltersIntoEnumerateCollection,
|
OptimizerRule::moveFiltersIntoEnumerateCollectionRule,
|
||||||
|
OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled));
|
||||||
|
|
||||||
|
registerRule("parallelize-gather", parallelizeGatherRule,
|
||||||
|
OptimizerRule::parallelizeGatherRule,
|
||||||
|
OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled,
|
||||||
|
OptimizerRule::Flags::ClusterOnly));
|
||||||
|
|
||||||
|
// apply late materialization for view queries
|
||||||
|
registerRule("late-document-materialization", arangodb::iresearch::lateDocumentMaterializationRule,
|
||||||
|
OptimizerRule::lateDocumentMaterializationRule,
|
||||||
OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled));
|
OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled));
|
||||||
|
|
||||||
|
// add the storage-engine specific rules
|
||||||
|
addStorageEngineRules();
|
||||||
|
|
||||||
// Splice subqueries
|
// Splice subqueries
|
||||||
//
|
//
|
||||||
// ***CAUTION***
|
// ***CAUTION***
|
||||||
|
@ -394,17 +407,10 @@ void OptimizerRulesFeature::addRules() {
|
||||||
OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled,
|
OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled,
|
||||||
OptimizerRule::Flags::DisabledByDefault));
|
OptimizerRule::Flags::DisabledByDefault));
|
||||||
|
|
||||||
// apply late materialization for view queries
|
|
||||||
registerRule("late-document-materialization", arangodb::iresearch::lateDocumentMaterializationRule,
|
|
||||||
OptimizerRule::lateDocumentMaterializationRule,
|
|
||||||
OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled));
|
|
||||||
|
|
||||||
// finally add the storage-engine specific rules
|
|
||||||
addStorageEngineRules();
|
|
||||||
|
|
||||||
// finally sort all rules by their level
|
// finally sort all rules by their level
|
||||||
std::sort(_rules.begin(), _rules.end(),
|
std::sort(_rules.begin(), _rules.end(),
|
||||||
[](OptimizerRule const& lhs, OptimizerRule const& rhs) {
|
[](OptimizerRule const& lhs, OptimizerRule const& rhs) noexcept {
|
||||||
return (lhs.level < rhs.level);
|
return (lhs.level < rhs.level);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1650,7 +1650,7 @@ function processQuery(query, explain, planIndex) {
|
||||||
return keyword('SCATTER');
|
return keyword('SCATTER');
|
||||||
case 'GatherNode':
|
case 'GatherNode':
|
||||||
let gatherAnnotations = [];
|
let gatherAnnotations = [];
|
||||||
if (node.isParallelizable) {
|
if (node.parallelism === 'parallel') {
|
||||||
gatherAnnotations.push('parallel');
|
gatherAnnotations.push('parallel');
|
||||||
}
|
}
|
||||||
if (node.sortmode !== 'unset') {
|
if (node.sortmode !== 'unset') {
|
||||||
|
|
Loading…
Reference in New Issue