mirror of https://gitee.com/bigwinds/arangodb
preparations for sort optimizer rule
This commit is contained in:
parent
4ad490eb47
commit
cd7c1bc453
|
@ -31,6 +31,7 @@
|
|||
#include "Aql/Ast.h"
|
||||
#include "Aql/AstNode.h"
|
||||
#include "Aql/ExecutionPlan.h"
|
||||
#include "Aql/SortCondition.h"
|
||||
#include "Aql/Variable.h"
|
||||
#include "Basics/Exceptions.h"
|
||||
#include "Basics/json.h"
|
||||
|
@ -194,15 +195,15 @@ void Condition::andCombine (AstNode const* node) {
|
|||
|
||||
bool Condition::findIndexes (EnumerateCollectionNode const* node,
|
||||
std::vector<Index const*>& usedIndexes,
|
||||
SortCondition const& sortCondition) {
|
||||
SortCondition const* sortCondition) {
|
||||
TRI_ASSERT(usedIndexes.empty());
|
||||
Variable const* reference = node->outVariable();
|
||||
|
||||
if (_root == nullptr) {
|
||||
// We do not have a condition. But we have a sort
|
||||
if (! sortCondition.isEmpty() &&
|
||||
sortCondition.isOnlyAttributeAccess() &&
|
||||
sortCondition.isUnidirectional()) {
|
||||
if (! sortCondition->isEmpty() &&
|
||||
sortCondition->isOnlyAttributeAccess() &&
|
||||
sortCondition->isUnidirectional()) {
|
||||
size_t const itemsInIndex = node->collection()->count();
|
||||
double bestCost = 0.0;
|
||||
Index const* bestIndex = nullptr;
|
||||
|
@ -249,11 +250,11 @@ bool Condition::findIndexes (EnumerateCollectionNode const* node,
|
|||
|
||||
bool Condition::indexSupportsSort (Index const* idx,
|
||||
Variable const* reference,
|
||||
SortCondition const& sortCondition,
|
||||
SortCondition const* sortCondition,
|
||||
size_t itemsInIndex,
|
||||
double& estimatedCost) {
|
||||
if (idx->isSorted() &&
|
||||
idx->supportsSortCondition(&sortCondition, reference, itemsInIndex, estimatedCost)) {
|
||||
idx->supportsSortCondition(sortCondition, reference, itemsInIndex, estimatedCost)) {
|
||||
// index supports the sort condition
|
||||
return true;
|
||||
}
|
||||
|
@ -276,7 +277,7 @@ bool Condition::findIndexForAndNode (size_t position,
|
|||
Variable const* reference,
|
||||
EnumerateCollectionNode const* colNode,
|
||||
std::vector<Index const*>& usedIndexes,
|
||||
SortCondition const& sortCondition) {
|
||||
SortCondition const* sortCondition) {
|
||||
// We can only iterate through a proper DNF
|
||||
auto node = _root->getMember(position);
|
||||
TRI_ASSERT(node->type == NODE_TYPE_OPERATOR_NARY_AND);
|
||||
|
@ -309,9 +310,9 @@ bool Condition::findIndexForAndNode (size_t position,
|
|||
filterCost = itemsInIndex * 1.5;
|
||||
}
|
||||
|
||||
if (! sortCondition.isEmpty() &&
|
||||
sortCondition.isOnlyAttributeAccess() &&
|
||||
sortCondition.isUnidirectional()) {
|
||||
if (! sortCondition->isEmpty() &&
|
||||
sortCondition->isOnlyAttributeAccess() &&
|
||||
sortCondition->isUnidirectional()) {
|
||||
// only go in here if we actually have a sort condition and it can in
|
||||
// general be supported by an index. for this, a sort condition must not
|
||||
// be empty, must consist only of attribute access, and all attributes
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
|
||||
#include "Basics/Common.h"
|
||||
#include "Aql/AstNode.h"
|
||||
#include "Aql/SortCondition.h"
|
||||
#include "Basics/AttributeNameParser.h"
|
||||
#include "Basics/JsonHelper.h"
|
||||
|
||||
|
@ -43,6 +42,7 @@ namespace triagens {
|
|||
class EnumerateCollectionNode;
|
||||
class ExecutionPlan;
|
||||
struct Index;
|
||||
class SortCondition;
|
||||
struct Variable;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -242,7 +242,7 @@ namespace triagens {
|
|||
|
||||
bool findIndexes (EnumerateCollectionNode const*,
|
||||
std::vector<Index const*>&,
|
||||
SortCondition const&);
|
||||
SortCondition const*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief dump the condition
|
||||
|
@ -297,7 +297,7 @@ namespace triagens {
|
|||
|
||||
bool indexSupportsSort (Index const*,
|
||||
Variable const*,
|
||||
SortCondition const&,
|
||||
SortCondition const*,
|
||||
size_t,
|
||||
double&);
|
||||
|
||||
|
@ -309,7 +309,7 @@ namespace triagens {
|
|||
Variable const*,
|
||||
EnumerateCollectionNode const*,
|
||||
std::vector<Index const*>&,
|
||||
SortCondition const&);
|
||||
SortCondition const*);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private variables
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Condition finder, used to build up the Condition object
|
||||
///
|
||||
/// @file arangod/Aql/ConditionFinder.h
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
|
@ -33,6 +33,32 @@
|
|||
|
||||
using namespace triagens::aql;
|
||||
using EN = triagens::aql::ExecutionNode;
|
||||
|
||||
bool ConditionFinder::isInnerLoop (ExecutionNode const* node) const {
|
||||
while (node != nullptr) {
|
||||
if (! node->hasDependency()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
node = node->getFirstDependency();
|
||||
TRI_ASSERT(node != nullptr);
|
||||
|
||||
auto type = node->getType();
|
||||
|
||||
if (type == EN::ENUMERATE_COLLECTION ||
|
||||
type == EN::INDEX_RANGE ||
|
||||
type == EN::INDEX ||
|
||||
type == EN::ENUMERATE_LIST) {
|
||||
// we are contained in an outer loop
|
||||
return true;
|
||||
|
||||
// future potential optimization: check if the outer loop has 0 or 1
|
||||
// iterations. in this case it is still possible to remove the sort
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ConditionFinder::before (ExecutionNode* en) {
|
||||
if (! _variableDefinitions.empty() && en->canThrow()) {
|
||||
|
@ -133,19 +159,26 @@ bool ConditionFinder::before (ExecutionNode* en) {
|
|||
}
|
||||
|
||||
condition->normalize(_plan);
|
||||
|
||||
std::vector<Index const*> usedIndexes;
|
||||
SortCondition sortCondition(_sorts, _variableDefinitions);
|
||||
|
||||
std::unique_ptr<SortCondition> sortCondition;
|
||||
if (! isInnerLoop(en)) {
|
||||
// we cannot optimize away a sort if we're in an inner loop ourselves
|
||||
sortCondition.reset(new SortCondition(_sorts, _variableDefinitions));
|
||||
}
|
||||
else {
|
||||
sortCondition.reset(new SortCondition);
|
||||
}
|
||||
|
||||
if (condition->isEmpty() && sortCondition.isEmpty()) {
|
||||
if (condition->isEmpty() && sortCondition->isEmpty()) {
|
||||
// no filter conditions left
|
||||
break;
|
||||
}
|
||||
|
||||
if (condition->findIndexes(node, usedIndexes, sortCondition)) {
|
||||
std::vector<Index const*> usedIndexes;
|
||||
if (condition->findIndexes(node, usedIndexes, sortCondition.get())) {
|
||||
bool reverse = false;
|
||||
if (sortCondition.isUnidirectional()) {
|
||||
reverse = sortCondition.isDescending();
|
||||
if (sortCondition->isUnidirectional()) {
|
||||
reverse = sortCondition->isDescending();
|
||||
}
|
||||
|
||||
TRI_ASSERT(! usedIndexes.empty());
|
||||
|
@ -173,7 +206,7 @@ bool ConditionFinder::before (ExecutionNode* en) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool ConditionFinder::enterSubquery (ExecutionNode* super, ExecutionNode* sub) {
|
||||
bool ConditionFinder::enterSubquery (ExecutionNode*, ExecutionNode*) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Condition finder, used to build up the Condition object
|
||||
///
|
||||
/// @file arangod/Aql/ConditionFinder.h
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
|
@ -55,11 +55,11 @@ namespace triagens {
|
|||
~ConditionFinder () {
|
||||
}
|
||||
|
||||
std::vector<std::pair<AstNode const*, bool>> translateSorts () const;
|
||||
bool isInnerLoop (ExecutionNode const*) const;
|
||||
|
||||
bool before (ExecutionNode* en) override final;
|
||||
bool before (ExecutionNode*) override final;
|
||||
|
||||
bool enterSubquery (ExecutionNode* super, ExecutionNode* sub) final;
|
||||
bool enterSubquery (ExecutionNode*, ExecutionNode*) final;
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -1749,7 +1749,7 @@ int triagens::aql::useIndexesRule (Optimizer* opt,
|
|||
|
||||
std::unordered_map<size_t, ExecutionNode*> changes;
|
||||
|
||||
auto cleanupChanges = [&] () -> void {
|
||||
auto cleanupChanges = [&changes] () -> void {
|
||||
for (auto& v : changes) {
|
||||
delete v.second;
|
||||
}
|
||||
|
|
|
@ -40,12 +40,26 @@ using namespace triagens::aql;
|
|||
// --SECTION-- constructors / destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create an empty condition
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SortCondition::SortCondition ()
|
||||
: _expressions(),
|
||||
_fields(),
|
||||
_unidirectional(false),
|
||||
_onlyAttributeAccess(false),
|
||||
_ascending(true) {
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create the sort condition
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SortCondition::SortCondition (std::vector<std::pair<AstNode const*, bool>> const& expressions)
|
||||
: _expressions(expressions),
|
||||
_fields(),
|
||||
_unidirectional(true),
|
||||
_onlyAttributeAccess(true),
|
||||
_ascending(true) {
|
||||
|
|
|
@ -50,10 +50,15 @@ namespace triagens {
|
|||
|
||||
public:
|
||||
|
||||
SortCondition () = delete;
|
||||
SortCondition (SortCondition const&) = delete;
|
||||
SortCondition& operator= (SortCondition const&) = delete;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create an empty sort condition
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SortCondition ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create the sort condition
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
Loading…
Reference in New Issue