1
0
Fork 0

stronger split between identification of candidates and application of geo index rule

This commit is contained in:
Jan Christoph Uhde 2016-12-02 11:53:31 +01:00
parent f27a22db06
commit e0220be12d
1 changed files with 29 additions and 17 deletions

View File

@ -3925,20 +3925,24 @@ struct GeoIndexInfo{
operator bool() const { return node; } operator bool() const { return node; }
GeoIndexInfo() GeoIndexInfo()
: collectionNode(nullptr) : collectionNode(nullptr)
, sortOrFilterNode(nullptr)
, collection(nullptr) , collection(nullptr)
, node(nullptr) , node(nullptr)
, index(nullptr) , index(nullptr)
, range(0) , range(0)
, within(false) , within(false)
, lessgreaterequal(false) , lessgreaterequal(false)
, invalid(false)
{} {}
EnumerateCollectionNode* collectionNode; EnumerateCollectionNode* collectionNode;
ExecutionNode* sortOrFilterNode;
Collection const* collection; Collection const* collection;
AstNode const* node; AstNode const* node;
std::shared_ptr<arangodb::Index> index; std::shared_ptr<arangodb::Index> index;
double range; double range;
bool within; bool within;
bool lessgreaterequal; bool lessgreaterequal;
bool invalid; //use it
std::vector<std::string> longitude; std::vector<std::string> longitude;
std::vector<std::string> latitude; std::vector<std::string> latitude;
}; };
@ -4040,7 +4044,7 @@ geoDistanceFunctionArgCheck(std::pair<AstNode*,AstNode*> const& pair, ExecutionN
} }
bool applyGeoOptimization(bool near, ExecutionPlan* plan, ExecutionNode* node, GeoIndexInfo& info, bool asc){ bool applyGeoOptimization(bool near, ExecutionPlan* plan, GeoIndexInfo& info, bool asc){
auto const& functionArguments = info.node->getMember(0); auto const& functionArguments = info.node->getMember(0);
if(functionArguments->numMembers() < 4){ if(functionArguments->numMembers() < 4){
return false; return false;
@ -4049,8 +4053,8 @@ bool applyGeoOptimization(bool near, ExecutionPlan* plan, ExecutionNode* node, G
std::pair<AstNode*,AstNode*> argPair1 = { functionArguments->getMember(0), functionArguments->getMember(1) }; std::pair<AstNode*,AstNode*> argPair1 = { functionArguments->getMember(0), functionArguments->getMember(1) };
std::pair<AstNode*,AstNode*> argPair2 = { functionArguments->getMember(2), functionArguments->getMember(3) }; std::pair<AstNode*,AstNode*> argPair2 = { functionArguments->getMember(2), functionArguments->getMember(3) };
auto result1 = geoDistanceFunctionArgCheck(argPair1, node, plan, info); auto result1 = geoDistanceFunctionArgCheck(argPair1, info.sortOrFilterNode, plan, info);
auto result2 = geoDistanceFunctionArgCheck(argPair2, node, plan, info); auto result2 = geoDistanceFunctionArgCheck(argPair2, info.sortOrFilterNode, plan, info);
// xor only one argument pair shall have a geoIndex // xor only one argument pair shall have a geoIndex
if ( ( !result1 && !result2 ) || ( result1 && result2 ) ){ if ( ( !result1 && !result2 ) || ( result1 && result2 ) ){
@ -4094,7 +4098,7 @@ bool applyGeoOptimization(bool near, ExecutionPlan* plan, ExecutionNode* node, G
plan->registerNode(inode); plan->registerNode(inode);
condition.release(); condition.release();
plan->unlinkNode(node); plan->unlinkNode(info.sortOrFilterNode);
plan->replaceNode(cnode,inode); plan->replaceNode(cnode,inode);
//signal that plan has been changed //signal that plan has been changed
@ -4221,34 +4225,35 @@ GeoIndexInfo identifyGeoOptimizationCandidate(ExecutionNode::NodeType type, Exec
switch(type){ switch(type){
case EN::SORT: { case EN::SORT: {
return isDistanceFunction(node); rv = isDistanceFunction(node);
rv.sortOrFilterNode = n;
} }
break; break;
case EN::FILTER: { case EN::FILTER: {
return isGeoFilterExpression(node); rv = isGeoFilterExpression(node);
rv.sortOrFilterNode = n;
} }
break; break;
default: default:
return rv; ;
} }
return rv;
}; };
void checkNodesForGeoOptimization(ExecutionNode::NodeType type, ExecutionPlan* plan, bool& modified){ void checkNodesForGeoOptimization(ExecutionNode::NodeType type, ExecutionPlan* plan, std::vector<GeoIndexInfo>& infos){
SmallVector<ExecutionNode*>::allocator_type::arena_type a; SmallVector<ExecutionNode*>::allocator_type::arena_type a;
SmallVector<ExecutionNode*> nodes{a}; SmallVector<ExecutionNode*> nodes{a};
plan->findNodesOfType(nodes, EN::SORT, true); plan->findNodesOfType(nodes, type, true);
for (auto const& n : nodes) { for (auto const& n : nodes) {
auto geoRequestDescripton = identifyGeoOptimizationCandidate(EN::SORT, plan, n); auto geoIndexInfo = identifyGeoOptimizationCandidate(type, plan, n);
if(!geoRequestDescripton){ if(!geoIndexInfo){
continue; continue;
} }
infos.push_back(std::move(geoIndexInfo));
LOG_TOPIC(DEBUG, Logger::DEVEL) << " FOUND NEAR OR WITHIN"; LOG_TOPIC(DEBUG, Logger::DEVEL) << " FOUND NEAR OR WITHIN";
if (applyGeoOptimization(true, plan, n, geoRequestDescripton, true)){
modified = true;
}
} }
} }
@ -4258,9 +4263,16 @@ void arangodb::aql::optimizeGeoIndexRule(Optimizer* opt,
LOG_TOPIC(DEBUG, Logger::DEVEL) << "ENTER GEO RULE"; LOG_TOPIC(DEBUG, Logger::DEVEL) << "ENTER GEO RULE";
std::vector<GeoIndexInfo> infos;
checkNodesForGeoOptimization(EN::SORT, plan, infos);
checkNodesForGeoOptimization(EN::FILTER, plan, infos);
bool modified = false; bool modified = false;
checkNodesForGeoOptimization(EN::SORT, plan, modified); for(auto& info : infos){
checkNodesForGeoOptimization(EN::FILTER, plan, modified); if (applyGeoOptimization(true, plan, info, true)){
modified = true;
}
}
opt->addPlan(plan, rule, modified); opt->addPlan(plan, rule, modified);
LOG_TOPIC(DEBUG, Logger::DEVEL) << "EXIT GEO RULE"; LOG_TOPIC(DEBUG, Logger::DEVEL) << "EXIT GEO RULE";