1
0
Fork 0

fixed usage of sparse indexes

This commit is contained in:
Jan Steemann 2015-10-19 10:56:30 +02:00
parent 37e76084bb
commit e5761736d4
3 changed files with 29 additions and 24 deletions

View File

@ -508,6 +508,10 @@ bool Index::canUseConditionPart (triagens::aql::AstNode const* access,
triagens::aql::Variable const* reference) const {
if (_sparse) {
if (op->type == triagens::aql::NODE_TYPE_OPERATOR_BINARY_NIN) {
return false;
}
if (op->type == triagens::aql::NODE_TYPE_OPERATOR_BINARY_IN &&
other->type == triagens::aql::NODE_TYPE_EXPANSION) {
// value IN a.b
@ -525,15 +529,23 @@ bool Index::canUseConditionPart (triagens::aql::AstNode const* access,
return false;
}
if (other->isNullValue()) {
if (op->type == triagens::aql::NODE_TYPE_OPERATOR_BINARY_LT ||
op->type == triagens::aql::NODE_TYPE_OPERATOR_BINARY_LE) {
// < and <= are not supported with sparse indexes as this may include null values
return false;
}
TRI_ASSERT_EXPENSIVE(other->isConstant());
if (other->isNullValue() &&
(op->type == triagens::aql::NODE_TYPE_OPERATOR_BINARY_EQ ||
op->type == triagens::aql::NODE_TYPE_OPERATOR_BINARY_GE)) {
// == and >= null are not supported with sparse indexes for the same reason
return false;
}
if (op->type == triagens::aql::NODE_TYPE_OPERATOR_BINARY_IN &&
other->type == triagens::aql::NODE_TYPE_ARRAY) {
size_t const n = other->numMembers();
for (size_t i = 0; i < n; ++i) {
if (other->getMemberUnchecked(i)->isNullValue()) {
return false;

View File

@ -1203,7 +1203,12 @@ bool SkiplistIndex::supportsFilterCondition (triagens::aql::AstNode const* node,
return true;
}
if (attributesCovered > 0) {
if (attributesCovered > 0 &&
(! _sparse || (_sparse && attributesCovered == _fields.size()))) {
// if the condition contains at least one index attribute and is not sparse,
// or the index is sparse and all attributes are covered by the condition,
// then it can be used (note: additional checks for condition parts in
// sparse indexes are contained in Index::canUseConditionPart)
estimatedItems = static_cast<size_t>((std::max)(static_cast<size_t>(estimatedCost * values), static_cast<size_t>(1)));
estimatedCost *= static_cast<double>(values);
return true;

View File

@ -2464,34 +2464,22 @@ function optimizerIndexesTestSuite () {
c.ensureSkiplist("value2", "value3", { sparse: true });
var queries = [
["FOR i IN " + c.name() + " FILTER i.value2 == 2 RETURN i.value", true],
["FOR i IN " + c.name() + " FILTER i.value3 == 2 RETURN i.value", false]
"FOR i IN " + c.name() + " FILTER i.value2 == 2 RETURN i.value",
"FOR i IN " + c.name() + " FILTER i.value3 == 2 RETURN i.value"
];
queries.forEach(function(query) {
var plan = AQL_EXPLAIN(query[0]).plan;
var plan = AQL_EXPLAIN(query).plan;
var nodeTypes = plan.nodes.map(function(node) {
return node.type;
});
var results;
if (query[1]) {
// Can use Index
assertNotEqual(-1, nodeTypes.indexOf("IndexNode"), query[0]);
results = AQL_EXECUTE(query[0]);
assertEqual([ 2 ], results.json, query[0]);
assertTrue(results.stats.scannedIndex > 0);
assertEqual(0, results.stats.scannedFull);
}
else {
// Cannot use Index
assertEqual(-1, nodeTypes.indexOf("IndexNode"), query[0]);
results = AQL_EXECUTE(query[0]);
assertEqual([ 2 ], results.json, query[0]);
assertTrue(results.stats.scannedFull > 0);
assertEqual(0, results.stats.scannedIndex);
}
// Cannot use Index
assertEqual(-1, nodeTypes.indexOf("IndexNode"), query);
var results = AQL_EXECUTE(query);
assertEqual([ 2 ], results.json, query);
assertTrue(results.stats.scannedFull > 0);
assertEqual(0, results.stats.scannedIndex);
});
},