1
0
Fork 0

preparations for sort optimizer rule

This commit is contained in:
Jan Steemann 2015-10-13 10:37:07 +02:00
parent 4ad490eb47
commit cd7c1bc453
7 changed files with 82 additions and 29 deletions

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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:

View File

@ -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;
}

View File

@ -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) {

View File

@ -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
////////////////////////////////////////////////////////////////////////////////