mirror of https://gitee.com/bigwinds/arangodb
Reduce planning time of high depth Traversals (#3942)
* Improved the cost estimation of traversals to be independent from max search depth. This fixes #3917 * fix failing test on MSVC
This commit is contained in:
parent
a7b4599ff9
commit
613cc4f749
|
@ -1,6 +1,9 @@
|
|||
devel
|
||||
-----
|
||||
|
||||
* fixed issue #3917: traversals with high maximal depth take extremely long
|
||||
in planning phase.
|
||||
|
||||
* UI: fixed issue #3822: disabled name input field for system collections
|
||||
|
||||
* fixed issue #3741: fix terminal color output in Windows
|
||||
|
|
|
@ -61,6 +61,14 @@ static uint64_t checkTraversalDepthValue(AstNode const* node) {
|
|||
"invalid traversal depth");
|
||||
}
|
||||
double v = node->getDoubleValue();
|
||||
if (v > static_cast<double>(INT64_MAX)) {
|
||||
// we cannot safely represent this value in an int64_t.
|
||||
// which is already far bigger than we will ever traverse, so
|
||||
// we can safely abort here and not care about uint64_t.
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_QUERY_PARSE,
|
||||
"invalid traversal depth");
|
||||
}
|
||||
|
||||
double intpart;
|
||||
if (modf(v, &intpart) != 0.0 || v < 0.0) {
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_QUERY_PARSE,
|
||||
|
|
|
@ -532,7 +532,7 @@ double TraverserOptions::estimateCost(size_t& nrItems) const {
|
|||
size_t baseCreateItems = 0;
|
||||
double baseCost = costForLookupInfoList(_baseLookupInfos, baseCreateItems);
|
||||
|
||||
for (uint64_t depth = 0; depth < maxDepth; ++depth) {
|
||||
for (uint64_t depth = 0; depth < maxDepth && depth < 10; ++depth) {
|
||||
auto liList = _depthLookupInfo.find(depth);
|
||||
if (liList == _depthLookupInfo.end()) {
|
||||
// No LookupInfo for this depth use base
|
||||
|
@ -545,6 +545,12 @@ double TraverserOptions::estimateCost(size_t& nrItems) const {
|
|||
count *= createItems;
|
||||
}
|
||||
}
|
||||
|
||||
if (maxDepth > 10) {
|
||||
// We have a too high depth this cost will be pruned anyway
|
||||
cost *= (maxDepth - 10) * 10;
|
||||
count *= (maxDepth - 10) * 10;
|
||||
}
|
||||
nrItems = count;
|
||||
return cost;
|
||||
}
|
||||
|
|
|
@ -1644,7 +1644,82 @@ function complexInternaSuite () {
|
|||
let res = db._query(query);
|
||||
assertEqual(res.count(), 1);
|
||||
assertEqual(res.toArray(), [vertex.B]);
|
||||
}
|
||||
},
|
||||
|
||||
testLargeMaxDepth: function () {
|
||||
let query = `
|
||||
WITH ${vn}
|
||||
FOR v, e, p IN 1..4294967295 OUTBOUND "${vn}/A" ${en}
|
||||
FILTER p.edges[1]._id != "${edge.BC}"
|
||||
FILTER p.vertices[2]._id != "${vertex.C}"
|
||||
RETURN v._id`;
|
||||
|
||||
let res = db._query(query);
|
||||
assertEqual(res.count(), 1);
|
||||
assertEqual(res.toArray(), [vertex.B]);
|
||||
},
|
||||
|
||||
testInt64MaxMaxDepth: function () {
|
||||
let query = `
|
||||
WITH ${vn}
|
||||
FOR v, e, p IN 1..9223372036854775807 OUTBOUND "${vn}/A" ${en}
|
||||
FILTER p.edges[1]._id != "${edge.BC}"
|
||||
FILTER p.vertices[2]._id != "${vertex.C}"
|
||||
RETURN v._id`;
|
||||
|
||||
let res = db._query(query);
|
||||
assertEqual(res.count(), 1);
|
||||
assertEqual(res.toArray(), [vertex.B]);
|
||||
},
|
||||
|
||||
|
||||
testEvenLargerMaxDepth: function () {
|
||||
let query = `
|
||||
WITH ${vn}
|
||||
FOR v, e, p IN 1..18446744073709551615 OUTBOUND "${vn}/A" ${en}
|
||||
FILTER p.edges[1]._id != "${edge.BC}"
|
||||
FILTER p.vertices[2]._id != "${vertex.C}"
|
||||
RETURN v._id`;
|
||||
|
||||
try {
|
||||
db._query(query);
|
||||
fail();
|
||||
} catch (e) {
|
||||
assertEqual(e.errorNum, errors.ERROR_QUERY_PARSE.code);
|
||||
}
|
||||
},
|
||||
|
||||
testNegativeMinDepth: function () {
|
||||
let query = `
|
||||
WITH ${vn}
|
||||
FOR v, e, p IN -1..3 OUTBOUND "${vn}/A" ${en}
|
||||
FILTER p.edges[1]._id != "${edge.BC}"
|
||||
FILTER p.vertices[2]._id != "${vertex.C}"
|
||||
RETURN v._id`;
|
||||
try {
|
||||
db._query(query);
|
||||
fail();
|
||||
} catch (e) {
|
||||
assertEqual(e.errorNum, errors.ERROR_QUERY_PARSE.code);
|
||||
}
|
||||
},
|
||||
|
||||
testNegativeMaxDepth: function () {
|
||||
let query = `
|
||||
WITH ${vn}
|
||||
FOR v, e, p IN 1..-3 OUTBOUND "${vn}/A" ${en}
|
||||
FILTER p.edges[1]._id != "${edge.BC}"
|
||||
FILTER p.vertices[2]._id != "${vertex.C}"
|
||||
RETURN v._id`;
|
||||
|
||||
try {
|
||||
db._query(query);
|
||||
fail();
|
||||
} catch (e) {
|
||||
assertEqual(e.errorNum, errors.ERROR_QUERY_PARSE.code);
|
||||
}
|
||||
},
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue