1
0
Fork 0

make use of projections if the projected data is used by an IndexNode's condition (#8001)

This commit is contained in:
Jan 2019-01-21 23:11:17 +01:00 committed by GitHub
parent 7958ac1a68
commit cabeb8fc7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 42 additions and 10 deletions

View File

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

View File

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

View File

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