1
0
Fork 0

remove-redundant-sorts, initial

This commit is contained in:
Jan Steemann 2014-08-28 12:39:28 +02:00
parent 9d4b1b1c88
commit 2eb38c9657
9 changed files with 180 additions and 18 deletions

View File

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

View File

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

View File

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

View File

@ -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 ();
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------

View File

@ -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) {
@ -368,9 +365,17 @@ bool Expression::isMultipleAttributeAccess () const {
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

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

View File

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

View File

@ -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) {
@ -598,7 +631,7 @@ public:
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) {

View File

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