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/Ast.h"
|
||||||
#include "Aql/AstNode.h"
|
#include "Aql/AstNode.h"
|
||||||
#include "Aql/ExecutionPlan.h"
|
#include "Aql/ExecutionPlan.h"
|
||||||
|
#include "Aql/SortCondition.h"
|
||||||
#include "Aql/Variable.h"
|
#include "Aql/Variable.h"
|
||||||
#include "Basics/Exceptions.h"
|
#include "Basics/Exceptions.h"
|
||||||
#include "Basics/json.h"
|
#include "Basics/json.h"
|
||||||
|
@ -194,15 +195,15 @@ void Condition::andCombine (AstNode const* node) {
|
||||||
|
|
||||||
bool Condition::findIndexes (EnumerateCollectionNode const* node,
|
bool Condition::findIndexes (EnumerateCollectionNode const* node,
|
||||||
std::vector<Index const*>& usedIndexes,
|
std::vector<Index const*>& usedIndexes,
|
||||||
SortCondition const& sortCondition) {
|
SortCondition const* sortCondition) {
|
||||||
TRI_ASSERT(usedIndexes.empty());
|
TRI_ASSERT(usedIndexes.empty());
|
||||||
Variable const* reference = node->outVariable();
|
Variable const* reference = node->outVariable();
|
||||||
|
|
||||||
if (_root == nullptr) {
|
if (_root == nullptr) {
|
||||||
// We do not have a condition. But we have a sort
|
// We do not have a condition. But we have a sort
|
||||||
if (! sortCondition.isEmpty() &&
|
if (! sortCondition->isEmpty() &&
|
||||||
sortCondition.isOnlyAttributeAccess() &&
|
sortCondition->isOnlyAttributeAccess() &&
|
||||||
sortCondition.isUnidirectional()) {
|
sortCondition->isUnidirectional()) {
|
||||||
size_t const itemsInIndex = node->collection()->count();
|
size_t const itemsInIndex = node->collection()->count();
|
||||||
double bestCost = 0.0;
|
double bestCost = 0.0;
|
||||||
Index const* bestIndex = nullptr;
|
Index const* bestIndex = nullptr;
|
||||||
|
@ -249,11 +250,11 @@ bool Condition::findIndexes (EnumerateCollectionNode const* node,
|
||||||
|
|
||||||
bool Condition::indexSupportsSort (Index const* idx,
|
bool Condition::indexSupportsSort (Index const* idx,
|
||||||
Variable const* reference,
|
Variable const* reference,
|
||||||
SortCondition const& sortCondition,
|
SortCondition const* sortCondition,
|
||||||
size_t itemsInIndex,
|
size_t itemsInIndex,
|
||||||
double& estimatedCost) {
|
double& estimatedCost) {
|
||||||
if (idx->isSorted() &&
|
if (idx->isSorted() &&
|
||||||
idx->supportsSortCondition(&sortCondition, reference, itemsInIndex, estimatedCost)) {
|
idx->supportsSortCondition(sortCondition, reference, itemsInIndex, estimatedCost)) {
|
||||||
// index supports the sort condition
|
// index supports the sort condition
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -276,7 +277,7 @@ bool Condition::findIndexForAndNode (size_t position,
|
||||||
Variable const* reference,
|
Variable const* reference,
|
||||||
EnumerateCollectionNode const* colNode,
|
EnumerateCollectionNode const* colNode,
|
||||||
std::vector<Index const*>& usedIndexes,
|
std::vector<Index const*>& usedIndexes,
|
||||||
SortCondition const& sortCondition) {
|
SortCondition const* sortCondition) {
|
||||||
// We can only iterate through a proper DNF
|
// We can only iterate through a proper DNF
|
||||||
auto node = _root->getMember(position);
|
auto node = _root->getMember(position);
|
||||||
TRI_ASSERT(node->type == NODE_TYPE_OPERATOR_NARY_AND);
|
TRI_ASSERT(node->type == NODE_TYPE_OPERATOR_NARY_AND);
|
||||||
|
@ -309,9 +310,9 @@ bool Condition::findIndexForAndNode (size_t position,
|
||||||
filterCost = itemsInIndex * 1.5;
|
filterCost = itemsInIndex * 1.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! sortCondition.isEmpty() &&
|
if (! sortCondition->isEmpty() &&
|
||||||
sortCondition.isOnlyAttributeAccess() &&
|
sortCondition->isOnlyAttributeAccess() &&
|
||||||
sortCondition.isUnidirectional()) {
|
sortCondition->isUnidirectional()) {
|
||||||
// only go in here if we actually have a sort condition and it can in
|
// 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
|
// general be supported by an index. for this, a sort condition must not
|
||||||
// be empty, must consist only of attribute access, and all attributes
|
// be empty, must consist only of attribute access, and all attributes
|
||||||
|
|
|
@ -32,7 +32,6 @@
|
||||||
|
|
||||||
#include "Basics/Common.h"
|
#include "Basics/Common.h"
|
||||||
#include "Aql/AstNode.h"
|
#include "Aql/AstNode.h"
|
||||||
#include "Aql/SortCondition.h"
|
|
||||||
#include "Basics/AttributeNameParser.h"
|
#include "Basics/AttributeNameParser.h"
|
||||||
#include "Basics/JsonHelper.h"
|
#include "Basics/JsonHelper.h"
|
||||||
|
|
||||||
|
@ -43,6 +42,7 @@ namespace triagens {
|
||||||
class EnumerateCollectionNode;
|
class EnumerateCollectionNode;
|
||||||
class ExecutionPlan;
|
class ExecutionPlan;
|
||||||
struct Index;
|
struct Index;
|
||||||
|
class SortCondition;
|
||||||
struct Variable;
|
struct Variable;
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
@ -242,7 +242,7 @@ namespace triagens {
|
||||||
|
|
||||||
bool findIndexes (EnumerateCollectionNode const*,
|
bool findIndexes (EnumerateCollectionNode const*,
|
||||||
std::vector<Index const*>&,
|
std::vector<Index const*>&,
|
||||||
SortCondition const&);
|
SortCondition const*);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief dump the condition
|
/// @brief dump the condition
|
||||||
|
@ -297,7 +297,7 @@ namespace triagens {
|
||||||
|
|
||||||
bool indexSupportsSort (Index const*,
|
bool indexSupportsSort (Index const*,
|
||||||
Variable const*,
|
Variable const*,
|
||||||
SortCondition const&,
|
SortCondition const*,
|
||||||
size_t,
|
size_t,
|
||||||
double&);
|
double&);
|
||||||
|
|
||||||
|
@ -309,7 +309,7 @@ namespace triagens {
|
||||||
Variable const*,
|
Variable const*,
|
||||||
EnumerateCollectionNode const*,
|
EnumerateCollectionNode const*,
|
||||||
std::vector<Index const*>&,
|
std::vector<Index const*>&,
|
||||||
SortCondition const&);
|
SortCondition const*);
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// --SECTION-- private variables
|
// --SECTION-- private variables
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief Condition finder, used to build up the Condition object
|
/// @brief Condition finder, used to build up the Condition object
|
||||||
///
|
///
|
||||||
/// @file arangod/Aql/ConditionFinder.h
|
/// @file
|
||||||
///
|
///
|
||||||
/// DISCLAIMER
|
/// DISCLAIMER
|
||||||
///
|
///
|
||||||
|
@ -33,6 +33,32 @@
|
||||||
|
|
||||||
using namespace triagens::aql;
|
using namespace triagens::aql;
|
||||||
using EN = triagens::aql::ExecutionNode;
|
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) {
|
bool ConditionFinder::before (ExecutionNode* en) {
|
||||||
if (! _variableDefinitions.empty() && en->canThrow()) {
|
if (! _variableDefinitions.empty() && en->canThrow()) {
|
||||||
|
@ -133,19 +159,26 @@ bool ConditionFinder::before (ExecutionNode* en) {
|
||||||
}
|
}
|
||||||
|
|
||||||
condition->normalize(_plan);
|
condition->normalize(_plan);
|
||||||
|
|
||||||
std::vector<Index const*> usedIndexes;
|
std::unique_ptr<SortCondition> sortCondition;
|
||||||
SortCondition sortCondition(_sorts, _variableDefinitions);
|
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
|
// no filter conditions left
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (condition->findIndexes(node, usedIndexes, sortCondition)) {
|
std::vector<Index const*> usedIndexes;
|
||||||
|
if (condition->findIndexes(node, usedIndexes, sortCondition.get())) {
|
||||||
bool reverse = false;
|
bool reverse = false;
|
||||||
if (sortCondition.isUnidirectional()) {
|
if (sortCondition->isUnidirectional()) {
|
||||||
reverse = sortCondition.isDescending();
|
reverse = sortCondition->isDescending();
|
||||||
}
|
}
|
||||||
|
|
||||||
TRI_ASSERT(! usedIndexes.empty());
|
TRI_ASSERT(! usedIndexes.empty());
|
||||||
|
@ -173,7 +206,7 @@ bool ConditionFinder::before (ExecutionNode* en) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConditionFinder::enterSubquery (ExecutionNode* super, ExecutionNode* sub) {
|
bool ConditionFinder::enterSubquery (ExecutionNode*, ExecutionNode*) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief Condition finder, used to build up the Condition object
|
/// @brief Condition finder, used to build up the Condition object
|
||||||
///
|
///
|
||||||
/// @file arangod/Aql/ConditionFinder.h
|
/// @file
|
||||||
///
|
///
|
||||||
/// DISCLAIMER
|
/// DISCLAIMER
|
||||||
///
|
///
|
||||||
|
@ -55,11 +55,11 @@ namespace triagens {
|
||||||
~ConditionFinder () {
|
~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:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -1749,7 +1749,7 @@ int triagens::aql::useIndexesRule (Optimizer* opt,
|
||||||
|
|
||||||
std::unordered_map<size_t, ExecutionNode*> changes;
|
std::unordered_map<size_t, ExecutionNode*> changes;
|
||||||
|
|
||||||
auto cleanupChanges = [&] () -> void {
|
auto cleanupChanges = [&changes] () -> void {
|
||||||
for (auto& v : changes) {
|
for (auto& v : changes) {
|
||||||
delete v.second;
|
delete v.second;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,12 +40,26 @@ using namespace triagens::aql;
|
||||||
// --SECTION-- constructors / destructors
|
// --SECTION-- constructors / destructors
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief create an empty condition
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
SortCondition::SortCondition ()
|
||||||
|
: _expressions(),
|
||||||
|
_fields(),
|
||||||
|
_unidirectional(false),
|
||||||
|
_onlyAttributeAccess(false),
|
||||||
|
_ascending(true) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief create the sort condition
|
/// @brief create the sort condition
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
SortCondition::SortCondition (std::vector<std::pair<AstNode const*, bool>> const& expressions)
|
SortCondition::SortCondition (std::vector<std::pair<AstNode const*, bool>> const& expressions)
|
||||||
: _expressions(expressions),
|
: _expressions(expressions),
|
||||||
|
_fields(),
|
||||||
_unidirectional(true),
|
_unidirectional(true),
|
||||||
_onlyAttributeAccess(true),
|
_onlyAttributeAccess(true),
|
||||||
_ascending(true) {
|
_ascending(true) {
|
||||||
|
|
|
@ -50,10 +50,15 @@ namespace triagens {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
SortCondition () = delete;
|
|
||||||
SortCondition (SortCondition const&) = delete;
|
SortCondition (SortCondition const&) = delete;
|
||||||
SortCondition& operator= (SortCondition const&) = delete;
|
SortCondition& operator= (SortCondition const&) = delete;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief create an empty sort condition
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
SortCondition ();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief create the sort condition
|
/// @brief create the sort condition
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
Loading…
Reference in New Issue