From 9b49328218c7e25bfd2a7f19bb46b4653391da4b Mon Sep 17 00:00:00 2001 From: Max Neunhoeffer Date: Thu, 28 Aug 2014 13:46:46 +0200 Subject: [PATCH] Rearrange levels for optimizer rules. Use rules multiple times. --- arangod/Aql/Optimizer.cpp | 62 ++++++++++++++++++++++++++-------- arangod/Aql/OptimizerRules.cpp | 13 ++++--- 2 files changed, 56 insertions(+), 19 deletions(-) diff --git a/arangod/Aql/Optimizer.cpp b/arangod/Aql/Optimizer.cpp index 6ac8d4549f..ddb6247c99 100644 --- a/arangod/Aql/Optimizer.cpp +++ b/arangod/Aql/Optimizer.cpp @@ -188,16 +188,7 @@ void Optimizer::setupRules () { registerRule("move-filters-up", moveFiltersUpRule, 20); ////////////////////////////////////////////////////////////////////////////// - /// "Pass 2": interchange EnumerateCollection nodes in all possible ways - /// this is level 100, please never let new plans from higher - /// levels go back to this or lower levels! - ////////////////////////////////////////////////////////////////////////////// - - registerRule("interchangeAdjacentEnumerations", - interchangeAdjacentEnumerations, 100); - - ////////////////////////////////////////////////////////////////////////////// - /// "Pass 3": try to remove redundant or unnecessary nodes + /// "Pass 2": try to remove redundant or unnecessary nodes /// use levels between 101 and 199 for this ////////////////////////////////////////////////////////////////////////////// @@ -214,15 +205,58 @@ void Optimizer::setupRules () { registerRule("remove-redundant-sorts", removeRedundantSorts, 130); ////////////////////////////////////////////////////////////////////////////// - /// "Pass 4": use indexes if possible for FILTER and/or SORT nodes - /// use levels between 200 and 299 for this + /// "Pass 3": interchange EnumerateCollection nodes in all possible ways + /// this is level 500, please never let new plans from higher + /// levels go back to this or lower levels! + ////////////////////////////////////////////////////////////////////////////// + + registerRule("interchangeAdjacentEnumerations", + interchangeAdjacentEnumerations, 500); + + ////////////////////////////////////////////////////////////////////////////// + // "Pass 4": moving nodes "up" (potentially outside loops) (second try): + // please use levels between 501 and 599 here + ////////////////////////////////////////////////////////////////////////////// + + // move calculations up the dependency chain (to pull them out of + // inner loops etc.) + registerRule("move-calculations-up", moveCalculationsUpRule, 510); + + // move filters up the dependency chain (to make result sets as small + // as possible as early as possible) + registerRule("move-filters-up", moveFiltersUpRule, 520); + + ////////////////////////////////////////////////////////////////////////////// + /// "Pass 5": try to remove redundant or unnecessary nodes (second try) + /// use levels between 601 and 699 for this + ////////////////////////////////////////////////////////////////////////////// + + // remove filters from the query that are not necessary at all + // filters that are always true will be removed entirely + // filters that are always false will be replaced with a NoResults node + registerRule("remove-unnecessary-filters", removeUnnecessaryFiltersRule, 610); + + // remove calculations that are never necessary + registerRule("remove-unnecessary-calculations", + removeUnnecessaryCalculationsRule, 620); + + // remove redundant sort blocks + registerRule("remove-redundant-sorts", removeRedundantSorts, 630); + + ////////////////////////////////////////////////////////////////////////////// + /// "Pass 6": use indexes if possible for FILTER and/or SORT nodes + /// use levels between 701 and 799 for this ////////////////////////////////////////////////////////////////////////////// // try to find a filter after an enumerate collection and find an index . . . - registerRule("use-index-range", useIndexRange, 210); + registerRule("use-index-range", useIndexRange, 710); // try to find sort blocks which are superseeded by indexes - registerRule("use-index-for-sort", useIndexForSort, 220); + registerRule("use-index-for-sort", useIndexForSort, 720); + + ////////////////////////////////////////////////////////////////////////////// + /// END OF OPTIMISATIONS + ////////////////////////////////////////////////////////////////////////////// // Now sort them by level: std::stable_sort(_rules.begin(), _rules.end()); diff --git a/arangod/Aql/OptimizerRules.cpp b/arangod/Aql/OptimizerRules.cpp index ac2c54b127..893a9fb9ac 100644 --- a/arangod/Aql/OptimizerRules.cpp +++ b/arangod/Aql/OptimizerRules.cpp @@ -725,14 +725,17 @@ class sortToIndexNode : public WalkerWorker { ExecutionPlan* _plan; Optimizer::PlanList& _out; sortAnalysis* _sortNode; + int _level; public: sortToIndexNode (ExecutionPlan* plan, Optimizer::PlanList& out, - sortAnalysis* Node) + sortAnalysis* Node, + int level) : _plan(plan), _out(out), - _sortNode(Node) { + _sortNode(Node), + _level(level) { } //////////////////////////////////////////////////////////////////////////////// @@ -751,7 +754,7 @@ class sortToIndexNode : public WalkerWorker { //////////////////////////////////////////////////////////////////////////////// /// @brief check whether we can sort via an index. //////////////////////////////////////////////////////////////////////////////// - bool handleEnumerateCollectionNode(EnumerateCollectionNode* node) + bool handleEnumerateCollectionNode(EnumerateCollectionNode* node, int level) { auto variableName = node->getVariablesSetHere()[0]->name; auto result = _sortNode->getAttrsForVariableName(variableName); @@ -836,7 +839,7 @@ class sortToIndexNode : public WalkerWorker { return handleIndexRangeNode(static_cast(en)); case EN::ENUMERATE_COLLECTION: - return handleEnumerateCollectionNode(static_cast(en)); + return handleEnumerateCollectionNode(static_cast(en), _level); } return true; } @@ -852,7 +855,7 @@ int triagens::aql::useIndexForSort (Optimizer* opt, auto thisSortNode = static_cast(n); sortAnalysis node(thisSortNode); if (node.isAnalyzeable()) { - sortToIndexNode finder(plan, out, &node); + sortToIndexNode finder(plan, out, &node, level); thisSortNode->walk(&finder);/// todo auf der dependency anfangen } }