mirror of https://gitee.com/bigwinds/arangodb
make use of projections if the projected data is used by an IndexNode's condition (#8001)
This commit is contained in:
parent
7958ac1a68
commit
cabeb8fc7b
|
@ -91,7 +91,7 @@ void RocksDBOptimizerRules::reduceExtractionToProjectionRule(
|
|||
ExecutionNode* current = n->getFirstParent();
|
||||
while (current != nullptr) {
|
||||
bool doRegularCheck = false;
|
||||
|
||||
|
||||
if (current->getType() == EN::REMOVE) {
|
||||
RemoveNode const* removeNode = ExecutionNode::castTo<RemoveNode const*>(current);
|
||||
if (removeNode->inVariable() == v) {
|
||||
|
@ -145,6 +145,22 @@ void RocksDBOptimizerRules::reduceExtractionToProjectionRule(
|
|||
attributes.emplace(it.attributePath[0]);
|
||||
}
|
||||
}
|
||||
} else if (current->getType() == EN::INDEX) {
|
||||
Condition const* condition = ExecutionNode::castTo<IndexNode const*>(current)->condition();
|
||||
|
||||
if (condition != nullptr && condition->root() != nullptr) {
|
||||
AstNode const* node = condition->root();
|
||||
vars.clear();
|
||||
current->getVariablesUsedHere(vars);
|
||||
|
||||
if (vars.find(v) != vars.end()) {
|
||||
if (!Ast::getReferencedAttributes(node, v, attributes)) {
|
||||
stop = true;
|
||||
break;
|
||||
}
|
||||
optimize = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// all other node types mandate a check
|
||||
doRegularCheck = true;
|
||||
|
@ -170,12 +186,8 @@ void RocksDBOptimizerRules::reduceExtractionToProjectionRule(
|
|||
|
||||
// projections are currently limited (arbitrarily to 5 attributes)
|
||||
if (optimize && !stop && !attributes.empty() && attributes.size() <= 5) {
|
||||
std::vector<std::string> r;
|
||||
for (auto& it : attributes) {
|
||||
r.emplace_back(std::move(it));
|
||||
}
|
||||
// store projections in DocumentProducingNode
|
||||
e->projections(std::move(r));
|
||||
e->projections(std::move(attributes));
|
||||
|
||||
if (n->getType() == ExecutionNode::INDEX) {
|
||||
// need to update _indexCoversProjections value in an IndexNode
|
||||
|
|
|
@ -288,7 +288,6 @@ bool RocksDBPrimaryIndexInIterator::nextCovering(DocumentCallback const& cb, siz
|
|||
}
|
||||
|
||||
while (limit > 0) {
|
||||
// TODO: prevent copying of the value into result, as we don't need it here!
|
||||
LocalDocumentId documentId = _index->lookupKey(_trx, StringRef(*_iterator));
|
||||
if (documentId.isSet()) {
|
||||
cb(documentId, *_iterator);
|
||||
|
|
|
@ -228,15 +228,36 @@ function optimizerRuleTestSuite () {
|
|||
result = AQL_EXECUTE(query[0], { "@cn" : cn });
|
||||
assertEqual(query[1], result.json);
|
||||
});
|
||||
},
|
||||
|
||||
testJoin : function () {
|
||||
c.ensureIndex({ type: "skiplist", fields: ["value"] });
|
||||
|
||||
let queries = [
|
||||
"FOR doc1 IN @@cn FOR doc2 IN @@cn FILTER doc1.value == doc2._key RETURN [doc1._key, doc2._key]",
|
||||
"FOR doc1 IN @@cn FOR doc2 IN @@cn FILTER doc1.value == doc2._key RETURN [doc1.value, doc2._key]",
|
||||
];
|
||||
|
||||
queries.forEach(function(query) {
|
||||
let result = AQL_EXPLAIN(query, { "@cn" : cn });
|
||||
assertNotEqual(-1, result.plan.rules.indexOf(ruleName), query);
|
||||
|
||||
let found = 0;
|
||||
result.plan.nodes.filter(function(node) {
|
||||
return node.type === 'IndexNode' || node.type === 'EnumerateCollectionNode';
|
||||
}).forEach(function(node) {
|
||||
assertNotEqual([], node.projections);
|
||||
++found;
|
||||
});
|
||||
|
||||
assertEqual(2, found);
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief executes the test suite
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
jsunity.run(optimizerRuleTestSuite);
|
||||
|
||||
return jsunity.done();
|
||||
|
|
Loading…
Reference in New Issue