mirror of https://gitee.com/bigwinds/arangodb
remove-redundant-sorts, initial
This commit is contained in:
parent
9d4b1b1c88
commit
2eb38c9657
|
@ -814,6 +814,31 @@ void AstNode::append (triagens::basics::StringBuffer* buffer) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief stringify a node
|
||||||
|
/// note that currently stringification is only supported for certain node types
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
std::string AstNode::stringify () const {
|
||||||
|
switch (type) {
|
||||||
|
case NODE_TYPE_ATTRIBUTE_ACCESS: {
|
||||||
|
auto member = getMember(0);
|
||||||
|
return member->stringify() + std::string(".") + getStringValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
case NODE_TYPE_REFERENCE: {
|
||||||
|
auto variable = static_cast<Variable*>(getData());
|
||||||
|
TRI_ASSERT(variable != nullptr);
|
||||||
|
return variable->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "stringification not supported for node type");
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// --SECTION-- private methods
|
// --SECTION-- private methods
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
|
@ -493,6 +493,13 @@ namespace triagens {
|
||||||
|
|
||||||
void append (triagens::basics::StringBuffer*) const;
|
void append (triagens::basics::StringBuffer*) const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief stringify a node
|
||||||
|
/// note that currently stringification is only supported for certain node types
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
std::string stringify () const;
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// --SECTION-- private methods
|
// --SECTION-- private methods
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
#include "Aql/ExecutionNode.h"
|
#include "Aql/ExecutionNode.h"
|
||||||
#include "Aql/Collection.h"
|
#include "Aql/Collection.h"
|
||||||
|
#include "Aql/ExecutionPlan.h"
|
||||||
#include "Aql/WalkerWorker.h"
|
#include "Aql/WalkerWorker.h"
|
||||||
#include "Aql/Ast.h"
|
#include "Aql/Ast.h"
|
||||||
|
|
||||||
|
@ -70,7 +71,7 @@ std::unordered_map<int, std::string const> const ExecutionNode::TypeNames{
|
||||||
/// @brief returns the type name of the node
|
/// @brief returns the type name of the node
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
const std::string& ExecutionNode::getTypeString () const {
|
std::string const& ExecutionNode::getTypeString () const {
|
||||||
auto it = TypeNames.find(static_cast<int>(getType()));
|
auto it = TypeNames.find(static_cast<int>(getType()));
|
||||||
if (it != TypeNames.end()) {
|
if (it != TypeNames.end()) {
|
||||||
return (*it).second;
|
return (*it).second;
|
||||||
|
@ -918,6 +919,44 @@ std::vector<std::pair<ExecutionNode*, bool>> SortNode::getCalcNodePairs ()
|
||||||
return findExp._myVars;
|
return findExp._myVars;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief returns all sort information
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
SortInformation SortNode::getSortInformation (ExecutionPlan* plan) const {
|
||||||
|
SortInformation result;
|
||||||
|
|
||||||
|
auto elements = getElements();
|
||||||
|
for (auto it = elements.begin(); it != elements.end(); ++it) {
|
||||||
|
auto variable = (*it).first;
|
||||||
|
TRI_ASSERT(variable != nullptr);
|
||||||
|
auto setter = plan->getVarSetBy(variable->id);
|
||||||
|
|
||||||
|
if (setter == nullptr) {
|
||||||
|
result.isValid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setter->getType() == ExecutionNode::CALCULATION) {
|
||||||
|
// variable introduced by a calculation
|
||||||
|
auto expression = static_cast<CalculationNode*>(setter)->expression();
|
||||||
|
|
||||||
|
if (! expression->isAttributeAccess() &&
|
||||||
|
! expression->isReference()) {
|
||||||
|
result.isComplex = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.criteria.emplace_back(std::make_tuple(setter, expression->stringify(), (*it).second));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result.criteria.emplace_back(std::make_tuple(setter, variable->name, (*it).second));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// --SECTION-- methods of AggregateNode
|
// --SECTION-- methods of AggregateNode
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
|
@ -154,7 +154,7 @@ namespace triagens {
|
||||||
/// @brief return the type name of the node
|
/// @brief return the type name of the node
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
const std::string &getTypeString () const;
|
std::string const& getTypeString () const;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief checks whether we know a type of this kind; throws exception if not.
|
/// @brief checks whether we know a type of this kind; throws exception if not.
|
||||||
|
@ -1413,6 +1413,20 @@ namespace triagens {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// --SECTION-- struct SortInformation
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief this is an auxilliary struct for processed sort criteria information
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
struct SortInformation {
|
||||||
|
std::vector<std::tuple<ExecutionNode const*, std::string, bool>> criteria;
|
||||||
|
bool isValid = true;
|
||||||
|
bool isComplex = false;
|
||||||
|
};
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// --SECTION-- class SortNode
|
// --SECTION-- class SortNode
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
@ -1493,10 +1507,16 @@ namespace triagens {
|
||||||
/// @brief get Variables Used Here including ASC/DESC
|
/// @brief get Variables Used Here including ASC/DESC
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
std::vector<std::pair<Variable const*, bool>> getElements () {
|
std::vector<std::pair<Variable const*, bool>> getElements () const {
|
||||||
return _elements;
|
return _elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief returns all sort information
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
SortInformation getSortInformation (ExecutionPlan*) const;
|
||||||
|
|
||||||
std::vector<std::pair<ExecutionNode*, bool>> getCalcNodePairs ();
|
std::vector<std::pair<ExecutionNode*, bool>> getCalcNodePairs ();
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
|
@ -347,14 +347,11 @@ AqlValue Expression::executeSimpleExpression (AstNode const* node,
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief check whether this is a simple access to a variable with n attributes.
|
/// @brief check whether this is an attribute access of any degree (e.g. a.b,
|
||||||
|
/// a.b.c, ...)
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
bool Expression::isMultipleAttributeAccess () const {
|
bool Expression::isAttributeAccess () const {
|
||||||
if (!isSimple()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto expNode = _node;
|
auto expNode = _node;
|
||||||
|
|
||||||
if (expNode->type != triagens::aql::NODE_TYPE_ATTRIBUTE_ACCESS) {
|
if (expNode->type != triagens::aql::NODE_TYPE_ATTRIBUTE_ACCESS) {
|
||||||
|
@ -362,15 +359,23 @@ bool Expression::isMultipleAttributeAccess () const {
|
||||||
}
|
}
|
||||||
|
|
||||||
while (expNode->type == triagens::aql::NODE_TYPE_ATTRIBUTE_ACCESS) {
|
while (expNode->type == triagens::aql::NODE_TYPE_ATTRIBUTE_ACCESS) {
|
||||||
expNode = expNode->getMember (0);
|
expNode = expNode->getMember(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (expNode->type == triagens::aql::NODE_TYPE_REFERENCE);
|
return (expNode->type == triagens::aql::NODE_TYPE_REFERENCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief check whether this is a reference access
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool Expression::isReference () const {
|
||||||
|
return (_node->type == triagens::aql::NODE_TYPE_REFERENCE);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief this gives you ("variable.access", "Reference")
|
/// @brief this gives you ("variable.access", "Reference")
|
||||||
/// call isSimpleAccessReference in advance to enshure no exceptions.
|
/// call isSimpleAccessReference in advance to ensure no exceptions.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
std::pair<std::string, std::string> Expression::getMultipleAttributes() const {
|
std::pair<std::string, std::string> Expression::getMultipleAttributes() const {
|
||||||
if (!isSimple()) {
|
if (!isSimple()) {
|
||||||
|
@ -411,6 +416,14 @@ std::pair<std::string, std::string> Expression::getMultipleAttributes() const {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief stringify an expression
|
||||||
|
/// note that currently stringification is only supported for certain node types
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
std::string Expression::stringify () const {
|
||||||
|
return _node->stringify();
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// --SECTION-- END-OF-FILE
|
// --SECTION-- END-OF-FILE
|
||||||
|
|
|
@ -151,18 +151,32 @@ namespace triagens {
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief check whether this is a simple access to a variable with n attributes.
|
/// @brief check whether this is an attribute access of any degree (e.g. a.b,
|
||||||
|
/// a.b.c, ...)
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
bool isMultipleAttributeAccess () const;
|
bool isAttributeAccess () const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief check whether this is only a reference access
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool isReference () const;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief this gives you ("variable.access", "Reference")
|
/// @brief this gives you ("variable.access", "Reference")
|
||||||
/// call isSimpleAccessReference in advance to enshure no exceptions.
|
/// call isSimpleAccessReference in advance to ensure no exceptions.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
std::pair<std::string, std::string> getMultipleAttributes() const;
|
std::pair<std::string, std::string> getMultipleAttributes() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief stringify an expression
|
||||||
|
/// note that currently stringification is only supported for certain node types
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
std::string stringify () const;
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// --SECTION-- private functions
|
// --SECTION-- private functions
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
|
@ -170,10 +170,14 @@ void Optimizer::setupRules () {
|
||||||
TRI_ASSERT(_rules.empty());
|
TRI_ASSERT(_rules.empty());
|
||||||
|
|
||||||
// List all the rules in the system here:
|
// List all the rules in the system here:
|
||||||
|
// lower level values mean earlier rule execution
|
||||||
|
// if two rules have the same level value, they will be executed in declaration order
|
||||||
|
|
||||||
// try to find sort blocks which are superseeded by indexes
|
// try to find sort blocks which are superseeded by indexes
|
||||||
registerRule("use-index-for-sort", useIndexForSort, 2000);
|
registerRule("use-index-for-sort", useIndexForSort, 2000);
|
||||||
|
|
||||||
|
// remove redundant sort blocks
|
||||||
|
registerRule("remove-redundant-sorts", removeRedundantSorts, 1000);
|
||||||
|
|
||||||
// try to find a filter after an enumerate collection and find an index . . .
|
// try to find a filter after an enumerate collection and find an index . . .
|
||||||
registerRule("use-index-range", useIndexRange, 999);
|
registerRule("use-index-range", useIndexRange, 999);
|
||||||
|
|
|
@ -49,6 +49,38 @@ int triagens::aql::dummyRule (Optimizer*,
|
||||||
return TRI_ERROR_NO_ERROR;
|
return TRI_ERROR_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief remove redundant sorts
|
||||||
|
/// this rule modifies the plan in place:
|
||||||
|
/// - sorts that are covered by earlier sorts will be removed
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
int triagens::aql::removeRedundantSorts (Optimizer* opt,
|
||||||
|
ExecutionPlan* plan,
|
||||||
|
int level,
|
||||||
|
Optimizer::PlanList& out) {
|
||||||
|
// should we enter subqueries??
|
||||||
|
std::vector<ExecutionNode*> nodes = plan->findNodesOfType(triagens::aql::ExecutionNode::SORT, true);
|
||||||
|
|
||||||
|
for (auto n : nodes) {
|
||||||
|
auto sortInfo = static_cast<SortNode*>(n)->getSortInformation(plan);
|
||||||
|
|
||||||
|
if (sortInfo.isValid) {
|
||||||
|
/*
|
||||||
|
TODO: finalize
|
||||||
|
std::cout << "FOUND SORT:\n";
|
||||||
|
for (auto it = sortInfo.criteria.begin(); it != sortInfo.criteria.end(); ++it) {
|
||||||
|
std::cout << "- " << std::get<1>(*it) << ", " << std::get<2>(*it) << "\n";
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out.push_back(plan, level);
|
||||||
|
|
||||||
|
return TRI_ERROR_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief remove all unnecessary filters
|
/// @brief remove all unnecessary filters
|
||||||
/// this rule modifies the plan in place:
|
/// this rule modifies the plan in place:
|
||||||
|
@ -61,6 +93,7 @@ int triagens::aql::removeUnnecessaryFiltersRule (Optimizer* opt,
|
||||||
int level,
|
int level,
|
||||||
Optimizer::PlanList& out) {
|
Optimizer::PlanList& out) {
|
||||||
std::unordered_set<ExecutionNode*> toUnlink;
|
std::unordered_set<ExecutionNode*> toUnlink;
|
||||||
|
// should we enter subqueries??
|
||||||
std::vector<ExecutionNode*> nodes = plan->findNodesOfType(triagens::aql::ExecutionNode::FILTER, true);
|
std::vector<ExecutionNode*> nodes = plan->findNodesOfType(triagens::aql::ExecutionNode::FILTER, true);
|
||||||
|
|
||||||
for (auto n : nodes) {
|
for (auto n : nodes) {
|
||||||
|
@ -594,11 +627,11 @@ public:
|
||||||
d->ASC = sortParams[n].second;
|
d->ASC = sortParams[n].second;
|
||||||
d->calculationNodeID = sortParams[n].first->id();
|
d->calculationNodeID = sortParams[n].first->id();
|
||||||
|
|
||||||
if (sortParams[n].first->getType() == EN::CALCULATION) {
|
if (sortParams[n].first->getType() == EN::CALCULATION) {
|
||||||
auto cn = static_cast<triagens::aql::CalculationNode*>(sortParams[n].first);
|
auto cn = static_cast<triagens::aql::CalculationNode*>(sortParams[n].first);
|
||||||
auto oneSortExpression = cn->expression();
|
auto oneSortExpression = cn->expression();
|
||||||
|
|
||||||
if (oneSortExpression->isMultipleAttributeAccess()) {
|
if (oneSortExpression->isAttributeAccess()) {
|
||||||
auto simpleExpression = oneSortExpression->getMultipleAttributes();
|
auto simpleExpression = oneSortExpression->getMultipleAttributes();
|
||||||
d->variableName = simpleExpression.first;
|
d->variableName = simpleExpression.first;
|
||||||
d->attributevec = simpleExpression.second;
|
d->attributevec = simpleExpression.second;
|
||||||
|
@ -813,7 +846,6 @@ int triagens::aql::useIndexForSort (Optimizer* opt,
|
||||||
ExecutionPlan* plan,
|
ExecutionPlan* plan,
|
||||||
int level,
|
int level,
|
||||||
Optimizer::PlanList& out) {
|
Optimizer::PlanList& out) {
|
||||||
std::cout << plan->toJson(TRI_UNKNOWN_MEM_ZONE, false).toString() << "\n";
|
|
||||||
std::vector<ExecutionNode*> nodes
|
std::vector<ExecutionNode*> nodes
|
||||||
= plan->findNodesOfType(triagens::aql::ExecutionNode::SORT, true);
|
= plan->findNodesOfType(triagens::aql::ExecutionNode::SORT, true);
|
||||||
for (auto n : nodes) {
|
for (auto n : nodes) {
|
||||||
|
|
|
@ -46,6 +46,14 @@ namespace triagens {
|
||||||
|
|
||||||
int dummyRule (Optimizer*, ExecutionPlan*, int level, Optimizer::PlanList&);
|
int dummyRule (Optimizer*, ExecutionPlan*, int level, Optimizer::PlanList&);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief remove redundant sorts
|
||||||
|
/// this rule modifies the plan in place:
|
||||||
|
/// - sorts that are covered by earlier sorts will be removed
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
int removeRedundantSorts (Optimizer*, ExecutionPlan*, int level, Optimizer::PlanList&);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief remove all unnecessary filters
|
/// @brief remove all unnecessary filters
|
||||||
/// this rule modifies the plan in place:
|
/// this rule modifies the plan in place:
|
||||||
|
|
Loading…
Reference in New Issue