mirror of https://gitee.com/bigwinds/arangodb
fixed usage of sparse indexes
This commit is contained in:
parent
37e76084bb
commit
e5761736d4
|
@ -508,6 +508,10 @@ bool Index::canUseConditionPart (triagens::aql::AstNode const* access,
|
||||||
triagens::aql::Variable const* reference) const {
|
triagens::aql::Variable const* reference) const {
|
||||||
|
|
||||||
if (_sparse) {
|
if (_sparse) {
|
||||||
|
if (op->type == triagens::aql::NODE_TYPE_OPERATOR_BINARY_NIN) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (op->type == triagens::aql::NODE_TYPE_OPERATOR_BINARY_IN &&
|
if (op->type == triagens::aql::NODE_TYPE_OPERATOR_BINARY_IN &&
|
||||||
other->type == triagens::aql::NODE_TYPE_EXPANSION) {
|
other->type == triagens::aql::NODE_TYPE_EXPANSION) {
|
||||||
// value IN a.b
|
// value IN a.b
|
||||||
|
@ -525,15 +529,23 @@ bool Index::canUseConditionPart (triagens::aql::AstNode const* access,
|
||||||
return false;
|
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;
|
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 &&
|
if (op->type == triagens::aql::NODE_TYPE_OPERATOR_BINARY_IN &&
|
||||||
other->type == triagens::aql::NODE_TYPE_ARRAY) {
|
other->type == triagens::aql::NODE_TYPE_ARRAY) {
|
||||||
size_t const n = other->numMembers();
|
size_t const n = other->numMembers();
|
||||||
|
|
||||||
for (size_t i = 0; i < n; ++i) {
|
for (size_t i = 0; i < n; ++i) {
|
||||||
if (other->getMemberUnchecked(i)->isNullValue()) {
|
if (other->getMemberUnchecked(i)->isNullValue()) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -1203,7 +1203,12 @@ bool SkiplistIndex::supportsFilterCondition (triagens::aql::AstNode const* node,
|
||||||
return true;
|
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)));
|
estimatedItems = static_cast<size_t>((std::max)(static_cast<size_t>(estimatedCost * values), static_cast<size_t>(1)));
|
||||||
estimatedCost *= static_cast<double>(values);
|
estimatedCost *= static_cast<double>(values);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -2464,34 +2464,22 @@ function optimizerIndexesTestSuite () {
|
||||||
c.ensureSkiplist("value2", "value3", { sparse: true });
|
c.ensureSkiplist("value2", "value3", { sparse: true });
|
||||||
|
|
||||||
var queries = [
|
var queries = [
|
||||||
["FOR i IN " + c.name() + " FILTER i.value2 == 2 RETURN i.value", true],
|
"FOR i IN " + c.name() + " FILTER i.value2 == 2 RETURN i.value",
|
||||||
["FOR i IN " + c.name() + " FILTER i.value3 == 2 RETURN i.value", false]
|
"FOR i IN " + c.name() + " FILTER i.value3 == 2 RETURN i.value"
|
||||||
];
|
];
|
||||||
|
|
||||||
queries.forEach(function(query) {
|
queries.forEach(function(query) {
|
||||||
var plan = AQL_EXPLAIN(query[0]).plan;
|
var plan = AQL_EXPLAIN(query).plan;
|
||||||
var nodeTypes = plan.nodes.map(function(node) {
|
var nodeTypes = plan.nodes.map(function(node) {
|
||||||
return node.type;
|
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);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue