1
0
Fork 0

Merge branch 'devel' of github.com:triAGENS/ArangoDB into devel

This commit is contained in:
Frank Celler 2014-11-15 17:19:31 +01:00
commit 5961898fe9
5 changed files with 296 additions and 145 deletions

View File

@ -618,7 +618,9 @@ triagens::basics::Json ExecutionNode::toJsonHelperGeneric (triagens::basics::Jso
}
json("id", triagens::basics::Json(static_cast<double>(id())));
json("estimatedCost", triagens::basics::Json(getCost()));
size_t nrItems = 0;
json("estimatedCost", triagens::basics::Json(getCost(nrItems)));
json("estimatedNrItems", triagens::basics::Json(static_cast<double>(nrItems)));
if (verbose) {
json("depth", triagens::basics::Json(static_cast<double>(_depth)));
@ -1000,6 +1002,15 @@ void SingletonNode::toJsonHelper (triagens::basics::Json& nodes,
nodes(json);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief the cost of a singleton is 1, it produces one item only
////////////////////////////////////////////////////////////////////////////////
double SingletonNode::estimateCost (size_t& nrItems) const {
nrItems = 1;
return 1.0;
}
// -----------------------------------------------------------------------------
// --SECTION-- methods of EnumerateCollectionNode
// -----------------------------------------------------------------------------
@ -1165,6 +1176,20 @@ std::vector<EnumerateCollectionNode::IndexMatch>
return out;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief the cost of an enumerate collection node is a multiple of the cost of
/// its unique dependency
////////////////////////////////////////////////////////////////////////////////
double EnumerateCollectionNode::estimateCost (size_t& nrItems) const {
size_t incoming;
double depCost = _dependencies.at(0)->getCost(incoming);
size_t count = _collection->count();
nrItems = incoming * count;
return depCost + count * incoming;
// We do a full collection scan for each incoming item.
}
// -----------------------------------------------------------------------------
// --SECTION-- methods of EnumerateListNode
// -----------------------------------------------------------------------------
@ -1216,6 +1241,25 @@ ExecutionNode* EnumerateListNode::clone (ExecutionPlan* plan,
return static_cast<ExecutionNode*>(c);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief the cost of an enumerate list node
////////////////////////////////////////////////////////////////////////////////
double EnumerateListNode::estimateCost (size_t& nrItems) const {
size_t incoming = 0;
double depCost = _dependencies.at(0)->getCost(incoming);
nrItems = 100*incoming;
return depCost + 100.0 * incoming;
// Well, what can we say? The length of the list can in general
// only be determined at runtime... If we were to know that this
// list is constant, then we could maybe multiply by the length
// here... For the time being, we assume 100
}
// -----------------------------------------------------------------------------
// --SECTION-- methods of IndexRangeNode
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief toJson, for IndexRangeNode
////////////////////////////////////////////////////////////////////////////////
@ -1326,27 +1370,31 @@ ExecutionNode::IndexMatch IndexRangeNode::MatchesIndex (IndexMatchVec const& pat
/// @brief the cost of an index range node is a multiple of the cost of
/// its unique dependency
////////////////////////////////////////////////////////////////////////////////
double IndexRangeNode::estimateCost () const {
// the cost of the enumerate collection node we are replacing . . .
double const dependencyCost = _dependencies.at(0)->getCost();
double const oldCost = static_cast<double>(_collection->count()) * dependencyCost;
double IndexRangeNode::estimateCost (size_t& nrItems) const {
size_t incoming = 0;
double const dependencyCost = _dependencies.at(0)->getCost(incoming);
size_t docCount = _collection->count();
TRI_ASSERT(! _ranges.empty());
if (_index->type == TRI_IDX_TYPE_PRIMARY_INDEX) {
return dependencyCost;
nrItems = incoming;
return dependencyCost + nrItems;
}
if (_index->type == TRI_IDX_TYPE_EDGE_INDEX) {
return oldCost / 1000;
nrItems = incoming * docCount / 1000;
return dependencyCost + nrItems;
}
if (_index->type == TRI_IDX_TYPE_HASH_INDEX) {
if (_index->unique) {
return dependencyCost;
nrItems = incoming;
return dependencyCost + nrItems;
}
return oldCost / 1000;
nrItems = incoming * docCount / 1000;
return dependencyCost + nrItems;
}
if (_index->type == TRI_IDX_TYPE_SKIPLIST_INDEX) {
@ -1354,22 +1402,24 @@ double IndexRangeNode::estimateCost () const {
if (count == 0) {
// no ranges? so this is unlimited -> has to be more expensive
return oldCost;
nrItems = incoming * docCount;
return dependencyCost + nrItems;
}
if (_index->unique &&
count == _index->fields.size()) {
if (_ranges.at(0).back().is1ValueRangeInfo()) {
// unique index, all attributes compared using eq (==) operator
return dependencyCost;
nrItems = incoming;
return dependencyCost + nrItems;
}
}
double cost = oldCost;
double cost = static_cast<double>(docCount) * incoming;
for (auto x: _ranges.at(0)) { //only doing the 1-d case so far
if (x.is1ValueRangeInfo()) {
// equality lookup
cost /= 100;
cost /= 100.0;
continue;
}
@ -1385,11 +1435,11 @@ double IndexRangeNode::estimateCost () const {
if (hasLowerBound && hasUpperBound) {
// both lower and upper bounds defined
cost /= 10;
cost /= 10.0;
}
else if (hasLowerBound || hasUpperBound) {
// either only low or high bound defined
cost /= 2;
cost /= 2.0;
}
// each bound (const and dynamic) counts!
@ -1404,11 +1454,13 @@ double IndexRangeNode::estimateCost () const {
}
}
return cost;
nrItems = static_cast<size_t>(cost);
return dependencyCost + cost;
}
// no index
return dependencyCost;
nrItems = incoming * docCount;
return dependencyCost + nrItems;
}
////////////////////////////////////////////////////////////////////////////////
@ -1479,6 +1531,33 @@ void LimitNode::toJsonHelper (triagens::basics::Json& nodes,
nodes(json);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief estimateCost
////////////////////////////////////////////////////////////////////////////////
double LimitNode::estimateCost (size_t& nrItems) const {
size_t incoming = 0;
double depCost = _dependencies.at(0)->getCost(incoming);
if (incoming >= _offset + _limit) {
// We will actually only ask for _offset + _limit and hand
// on _limit:
nrItems = _limit;
return depCost * (_offset + _limit) / incoming + _limit;
}
else {
// We will only get less than we need, but at the full cost
// for the dependencies:
if (incoming >= _offset) {
nrItems = incoming - _offset;
return depCost + nrItems;
}
else {
nrItems = 0;
return depCost;
}
}
}
// -----------------------------------------------------------------------------
// --SECTION-- methods of CalculationNode
// -----------------------------------------------------------------------------
@ -1527,6 +1606,15 @@ ExecutionNode* CalculationNode::clone (ExecutionPlan* plan,
return static_cast<ExecutionNode*>(c);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief estimateCost
////////////////////////////////////////////////////////////////////////////////
double CalculationNode::estimateCost (size_t& nrItems) const {
double depCost = _dependencies.at(0)->getCost(nrItems);
return depCost + nrItems;
}
// -----------------------------------------------------------------------------
// --SECTION-- methods of SubqueryNode
// -----------------------------------------------------------------------------
@ -1577,6 +1665,17 @@ void SubqueryNode::replaceOutVariable(Variable const* var) {
_outVariable = var;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief estimateCost
////////////////////////////////////////////////////////////////////////////////
double SubqueryNode::estimateCost (size_t& nrItems) const {
double depCost = _dependencies.at(0)->getCost(nrItems);
size_t dummy;
double subCost = _subquery->getCost(dummy);
return depCost + nrItems * subCost;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief helper struct to find all (outer) variables used in a SubqueryNode
////////////////////////////////////////////////////////////////////////////////
@ -1720,6 +1819,24 @@ ExecutionNode* FilterNode::clone (ExecutionPlan* plan,
return static_cast<ExecutionNode*>(c);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief estimateCost
////////////////////////////////////////////////////////////////////////////////
double FilterNode::estimateCost (size_t& nrItems) const {
double depCost = _dependencies.at(0)->getCost(nrItems);
// We are pessimistic here by not reducing the nrItems. However, in the
// worst case the filter does not reduce the items at all. Furthermore,
// no optimiser rule introduces FilterNodes, thus it is not important
// that they appear to lower the costs. Note that contrary to this,
// an IndexRangeNode does lower the costs, it also has a better idea
// to what extent the number of items is reduced. On the other hand it
// is important that a FilterNode produces additional costs, otherwise
// the rule throwing away a FilterNode that is already covered by an
// IndexRangeNode cannot reduce the costs.
return depCost + nrItems;
}
// -----------------------------------------------------------------------------
// --SECTION-- methods of SortNode
// -----------------------------------------------------------------------------
@ -1848,6 +1965,18 @@ SortInformation SortNode::getSortInformation (ExecutionPlan* plan,
return result;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief estimateCost
////////////////////////////////////////////////////////////////////////////////
double SortNode::estimateCost (size_t& nrItems) const {
double depCost = _dependencies.at(0)->getCost(nrItems);
if (nrItems <= 3.0) {
return depCost + nrItems;
}
return depCost + nrItems * log(nrItems);
}
// -----------------------------------------------------------------------------
// --SECTION-- methods of AggregateNode
// -----------------------------------------------------------------------------
@ -1970,6 +2099,21 @@ std::vector<Variable const*> AggregateNode::getVariablesUsedHere () const {
return vv;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief estimateCost
////////////////////////////////////////////////////////////////////////////////
double AggregateNode::estimateCost (size_t& nrItems) const {
double depCost = _dependencies.at(0)->getCost(nrItems);
// As in the FilterNode case, we are pessimistic here by not reducing the
// nrItems, since this is the worst case. We have to look at all incoming
// items, and in particular in the COLLECT ... INTO ... case, we have
// to actually hand on all data anyway, albeit not as separate items.
// Nevertheless, the optimiser does not do much with AggregateNodes
// and thus this overestimation does not really matter.
return depCost + nrItems;
}
// -----------------------------------------------------------------------------
// --SECTION-- methods of ReturnNode
// -----------------------------------------------------------------------------
@ -2019,6 +2163,15 @@ ExecutionNode* ReturnNode::clone (ExecutionPlan* plan,
return static_cast<ExecutionNode*>(c);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief estimateCost
////////////////////////////////////////////////////////////////////////////////
double ReturnNode::estimateCost (size_t& nrItems) const {
double depCost = _dependencies.at(0)->getCost(nrItems);
return depCost + nrItems;
}
// -----------------------------------------------------------------------------
// --SECTION-- ModificationNode
// -----------------------------------------------------------------------------
@ -2048,6 +2201,19 @@ void ModificationNode::toJsonHelper (triagens::basics::Json& json,
_options.toJson(json, zone);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief estimateCost
/// Note that all the modifying nodes use this estimateCost method which is
/// why we can make it final here.
////////////////////////////////////////////////////////////////////////////////
double ModificationNode::estimateCost (size_t& nrItems) const {
size_t incoming = 0;
double depCost = _dependencies.at(0)->getCost(incoming);
nrItems = 0;
return depCost + incoming;
}
// -----------------------------------------------------------------------------
// --SECTION-- methods of RemoveNode
@ -2342,6 +2508,15 @@ void NoResultsNode::toJsonHelper (triagens::basics::Json& nodes,
nodes(json);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief estimateCost, the cost of a NoResults is nearly 0
////////////////////////////////////////////////////////////////////////////////
double NoResultsNode::estimateCost (size_t& nrItems) const {
nrItems = 0;
return 0.5; // just to make it non-zero
}
// -----------------------------------------------------------------------------
// --SECTION-- methods of RemoteNode
// -----------------------------------------------------------------------------
@ -2382,6 +2557,24 @@ void RemoteNode::toJsonHelper (triagens::basics::Json& nodes,
nodes(json);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief estimateCost
////////////////////////////////////////////////////////////////////////////////
double RemoteNode::estimateCost (size_t& nrItems) const {
double depCost;
if (_dependencies.size() == 1) {
// This will usually be the case, however, in the context of the
// instantiation it is possible that there is no dependency...
depCost = _dependencies[0]->estimateCost(nrItems);
return depCost + nrItems; // we need to process them all
}
// We really should not get here, but if so, do something bordering on
// sensible:
nrItems = 1;
return 1.0;
}
// -----------------------------------------------------------------------------
// --SECTION-- methods of ScatterNode
// -----------------------------------------------------------------------------
@ -2416,6 +2609,17 @@ void ScatterNode::toJsonHelper (triagens::basics::Json& nodes,
nodes(json);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief estimateCost
////////////////////////////////////////////////////////////////////////////////
double ScatterNode::estimateCost (size_t& nrItems) const {
double depCost = _dependencies[0]->getCost(nrItems);
std::vector<std::string> shardIds = _collection->shardIds();
size_t nrShards = shardIds.size();
return depCost + nrItems * nrShards;
}
// -----------------------------------------------------------------------------
// --SECTION-- methods of DistributeNode
// -----------------------------------------------------------------------------
@ -2449,6 +2653,15 @@ void DistributeNode::toJsonHelper (triagens::basics::Json& nodes,
nodes(json);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief estimateCost
////////////////////////////////////////////////////////////////////////////////
double DistributeNode::estimateCost (size_t& nrItems) const {
double depCost = _dependencies[0]->getCost(nrItems);
return depCost + nrItems;
}
// -----------------------------------------------------------------------------
// --SECTION-- methods of GatherNode
// -----------------------------------------------------------------------------
@ -2494,6 +2707,15 @@ void GatherNode::toJsonHelper (triagens::basics::Json& nodes,
nodes(json);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief estimateCost
////////////////////////////////////////////////////////////////////////////////
double GatherNode::estimateCost (size_t& nrItems) const {
double depCost = _dependencies[0]->getCost(nrItems);
return depCost + nrItems;
}
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"

View File

@ -116,6 +116,7 @@ namespace triagens {
ExecutionNode (ExecutionPlan* plan, size_t id)
: _id(id),
_estimatedCost(0.0),
_estimatedNrItems(0),
_estimatedCostSet(false),
_varUsageValid(false),
_plan(plan),
@ -383,19 +384,25 @@ namespace triagens {
/// @brief estimate the cost of the node . . .
////////////////////////////////////////////////////////////////////////////////
double getCost () const {
double getCost (size_t& nrItems) const {
if (! _estimatedCostSet) {
_estimatedCost = estimateCost();
_estimatedCost = estimateCost(_estimatedNrItems);
nrItems = _estimatedNrItems;
_estimatedCostSet = true;
TRI_ASSERT(_estimatedCost >= 0.0);
}
else {
nrItems = _estimatedNrItems;
}
return _estimatedCost;
};
virtual double estimateCost () const = 0;
////////////////////////////////////////////////////////////////////////////////
/// @brief this actually estimates the costs as well as the number of items
/// coming out of the node
////////////////////////////////////////////////////////////////////////////////
//TODO nodes should try harder to estimate their own cost, i.e. the cost
//of performing the operation of the node . . .
virtual double estimateCost (size_t& nrItems) const = 0;
////////////////////////////////////////////////////////////////////////////////
/// @brief walk a complete execution plan recursively
@ -674,11 +681,14 @@ namespace triagens {
////////////////////////////////////////////////////////////////////////////////
/// @brief _estimatedCost = 0 if uninitialised and otherwise stores the result
/// of estimateCost(), the bool indicates if the cost has been set, it starts
/// out as false
/// out as false, _estimatedNrItems is the estimated number of items coming
/// out of this node.
////////////////////////////////////////////////////////////////////////////////
double mutable _estimatedCost;
size_t mutable _estimatedNrItems;
bool mutable _estimatedCostSet;
////////////////////////////////////////////////////////////////////////////////
@ -791,9 +801,7 @@ namespace triagens {
/// @brief the cost of a singleton is 1
////////////////////////////////////////////////////////////////////////////////
double estimateCost () const override final {
return 1.0;
}
virtual double estimateCost (size_t&) const override final;
};
@ -862,10 +870,7 @@ namespace triagens {
/// its unique dependency
////////////////////////////////////////////////////////////////////////////////
double estimateCost () const override final {
return static_cast<double>(_collection->count()) * _dependencies.at(0)->getCost();
//FIXME improve this estimate . . .
}
virtual double estimateCost (size_t&) const override final;
////////////////////////////////////////////////////////////////////////////////
/// @brief getVariablesSetHere
@ -1014,10 +1019,7 @@ namespace triagens {
/// @brief the cost of an enumerate list node is . . . FIXME
////////////////////////////////////////////////////////////////////////////////
double estimateCost () const override final {
return 1000 * _dependencies.at(0)->getCost();
//FIXME improve this estimate . . .
}
virtual double estimateCost (size_t&) const override final;
////////////////////////////////////////////////////////////////////////////////
/// @brief getVariablesUsedHere
@ -1179,7 +1181,7 @@ namespace triagens {
/// @brief estimateCost
////////////////////////////////////////////////////////////////////////////////
double estimateCost () const override final;
virtual double estimateCost (size_t&) const override final;
////////////////////////////////////////////////////////////////////////////////
/// @brief check whether the pattern matches this node's index
@ -1309,14 +1311,10 @@ namespace triagens {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief the cost of a limit node is the minimum of the _limit, and the cost
/// the dependency . . .
/// @brief estimateCost
////////////////////////////////////////////////////////////////////////////////
double estimateCost () const override final {
return 1.005 * static_cast<double>(_limit) + _dependencies.at(0)->getCost();
// FIXME: improve this estimate . . .
}
double estimateCost (size_t&) const override final;
////////////////////////////////////////////////////////////////////////////////
/// @brief tell the node to fully count what it will limit
@ -1434,14 +1432,10 @@ namespace triagens {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief the cost of a calculation node is the cost of the unique dependency
// times a constant
/// @brief estimateCost
////////////////////////////////////////////////////////////////////////////////
double estimateCost () const override final {
return 2 * _dependencies.at(0)->getCost();
//FIXME improve this estimate . . .
}
double estimateCost (size_t&) const override final;
////////////////////////////////////////////////////////////////////////////////
/// @brief getVariablesUsedHere
@ -1572,14 +1566,10 @@ namespace triagens {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief the cost of a subquery node is the cost of its unique dependency
/// times a small constant
/// @brief estimateCost
////////////////////////////////////////////////////////////////////////////////
double estimateCost () const override final {
return 1.005 * _dependencies.at(0)->getCost();
//FIXME improve this estimate . . .
}
double estimateCost (size_t&) const override final;
////////////////////////////////////////////////////////////////////////////////
/// @brief getVariablesUsedHere
@ -1687,14 +1677,10 @@ namespace triagens {
bool withProperties) const;
////////////////////////////////////////////////////////////////////////////////
/// @brief the cost of a filter node is . . . FIXME
/// @brief estimateCost
////////////////////////////////////////////////////////////////////////////////
double estimateCost () const override final {
return _dependencies.at(0)->getCost() * 1.105;
// FIXME! 1.105 is the cost of doing the filter node under the
// assumption that it returns 10% of the results of its dependency
}
double estimateCost (size_t&) const override final;
////////////////////////////////////////////////////////////////////////////////
/// @brief getVariablesUsedHere
@ -1849,16 +1835,10 @@ namespace triagens {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief the cost of a sort node is . . . FIXME
/// @brief estimateCost
////////////////////////////////////////////////////////////////////////////////
double estimateCost () const override final {
double depCost = _dependencies.at(0)->getCost();
if (depCost <= 3.0) {
return depCost;
}
return log(depCost) * depCost;
}
double estimateCost (size_t&) const override final;
////////////////////////////////////////////////////////////////////////////////
/// @brief getVariablesUsedHere
@ -1974,13 +1954,10 @@ namespace triagens {
bool withProperties) const;
////////////////////////////////////////////////////////////////////////////////
/// @brief the cost of an aggregate node is . . . FIXME
/// @brief estimateCost
////////////////////////////////////////////////////////////////////////////////
double estimateCost () const override final {
return 2 * _dependencies.at(0)->getCost();
//FIXME improve this estimate . . .
}
double estimateCost (size_t&) const override final;
////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not the node has an outVariable (i.e. INTO ...)
@ -2094,12 +2071,10 @@ namespace triagens {
bool withProperties) const;
////////////////////////////////////////////////////////////////////////////////
/// @brief the cost of a return node is the cost of its only dependency . . .
/// @brief estimateCost
////////////////////////////////////////////////////////////////////////////////
double estimateCost () const override final {
return _dependencies.at(0)->getCost();
}
double estimateCost (size_t&) const override final;
////////////////////////////////////////////////////////////////////////////////
/// @brief getVariablesUsedHere
@ -2192,6 +2167,14 @@ namespace triagens {
return _collection;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief estimateCost
/// Note that all the modifying nodes use this estimateCost method which is
/// why we can make it final here.
////////////////////////////////////////////////////////////////////////////////
double estimateCost (size_t&) const override final;
// -----------------------------------------------------------------------------
// --SECTION-- protected variables
// -----------------------------------------------------------------------------
@ -2280,16 +2263,6 @@ namespace triagens {
bool withDependencies,
bool withProperties) const;
////////////////////////////////////////////////////////////////////////////////
/// @brief the cost of a remove node is a multiple of the cost of its unique
/// dependency
////////////////////////////////////////////////////////////////////////////////
double estimateCost () const override final {
return _dependencies.at(0)->getCost();
// TODO: improve this estimate!
}
////////////////////////////////////////////////////////////////////////////////
/// @brief getVariablesUsedHere
////////////////////////////////////////////////////////////////////////////////
@ -2393,15 +2366,6 @@ namespace triagens {
bool withDependencies,
bool withProperties) const;
////////////////////////////////////////////////////////////////////////////////
/// @brief the cost of an insert node is a multiple of the cost of its unique
/// dependency
////////////////////////////////////////////////////////////////////////////////
double estimateCost () const override final {
return 1000 * _dependencies.at(0)->getCost(); //FIXME change this!
}
////////////////////////////////////////////////////////////////////////////////
/// @brief getVariablesUsedHere
////////////////////////////////////////////////////////////////////////////////
@ -2508,15 +2472,6 @@ namespace triagens {
bool withDependencies,
bool withProperties) const;
////////////////////////////////////////////////////////////////////////////////
/// @brief the cost of an update node is a multiple of the cost of its unique
/// dependency
////////////////////////////////////////////////////////////////////////////////
double estimateCost () const override final {
return 1000 * _dependencies.at(0)->getCost(); //FIXME change this!
}
////////////////////////////////////////////////////////////////////////////////
/// @brief getVariablesUsedHere
////////////////////////////////////////////////////////////////////////////////
@ -2633,15 +2588,6 @@ namespace triagens {
bool withDependencies,
bool withProperties) const;
////////////////////////////////////////////////////////////////////////////////
/// @brief the cost of a replace node is a multiple of the cost of its unique
/// dependency
////////////////////////////////////////////////////////////////////////////////
double estimateCost () const override final {
return 1000 * _dependencies.at(0)->getCost(); //FIXME change this!
}
////////////////////////////////////////////////////////////////////////////////
/// @brief getVariablesUsedHere
////////////////////////////////////////////////////////////////////////////////
@ -2755,9 +2701,7 @@ namespace triagens {
/// @brief the cost of a NoResults is 0
////////////////////////////////////////////////////////////////////////////////
double estimateCost () const override final {
return 0.0;
}
double estimateCost (size_t&) const override final;
};
@ -2829,19 +2773,10 @@ namespace triagens {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief the cost of a remote node is that of its dependency,
/// times a factor for extra HTTP work
/// @brief estimateCost
////////////////////////////////////////////////////////////////////////////////
double estimateCost () const override final {
if (_dependencies.size() == 1) {
// the 1.5 is an arbitrary factor to account for some overhead of the
// remote processing, HTTP communication etc.
return 1.5 * _dependencies[0]->estimateCost();
}
return 1.5;
}
double estimateCost (size_t&) const override final;
////////////////////////////////////////////////////////////////////////////////
/// @brief return the database
@ -3012,12 +2947,10 @@ namespace triagens {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief the cost of a scatter node is 1
/// @brief estimateCost
////////////////////////////////////////////////////////////////////////////////
double estimateCost () const override final {
return 1.0;
}
double estimateCost (size_t&) const override final;
////////////////////////////////////////////////////////////////////////////////
/// @brief return the database
@ -3115,12 +3048,10 @@ namespace triagens {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief the cost of a distribute node is 1
/// @brief estimateCost
////////////////////////////////////////////////////////////////////////////////
double estimateCost () const override final {
return 1.0;
}
double estimateCost (size_t&) const override final;
////////////////////////////////////////////////////////////////////////////////
/// @brief return the database
@ -3223,12 +3154,10 @@ namespace triagens {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief the cost of a gather node is 1
/// @brief estimateCost
////////////////////////////////////////////////////////////////////////////////
double estimateCost () const override final {
return 1.0;
}
double estimateCost (size_t&) const override final;
////////////////////////////////////////////////////////////////////////////////
/// @brief getVariablesUsedHere

View File

@ -183,7 +183,9 @@ triagens::basics::Json ExecutionPlan::toJson (Ast* ast,
result.set("collections", jsonCollectionList);
result.set("variables", ast->variables()->toJson(TRI_UNKNOWN_MEM_ZONE));
result.set("estimatedCost", triagens::basics::Json(_root->getCost()));
size_t nrItems = 0;
result.set("estimatedCost", triagens::basics::Json(_root->getCost(nrItems)));
result.set("estimatedNrItems", triagens::basics::Json(static_cast<double>(nrItems)));
return result;
}

View File

@ -184,7 +184,8 @@ namespace triagens {
inline double getCost () {
TRI_ASSERT(_root != nullptr);
return _root->getCost();
size_t nrItems;
return _root->getCost(nrItems);
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -210,13 +210,11 @@ function explainSuite () {
assertEqual("SingletonNode", node.type);
assertEqual([ ], node.dependencies);
assertEqual(1, node.id);
assertEqual(1, node.estimatedCost);
node = nodes[1];
assertEqual("EnumerateCollectionNode", node.type);
assertEqual([ 1 ], node.dependencies);
assertEqual(2, node.id);
assertEqual(0, node.estimatedCost);
assertEqual("_system", node.database);
assertEqual(cn, node.collection);
assertEqual("i", node.outVariable.name);
@ -233,7 +231,6 @@ function explainSuite () {
assertEqual("FilterNode", node.type);
assertEqual([ 3 ], node.dependencies);
assertEqual(4, node.id);
assertEqual(0, node.estimatedCost);
assertEqual(out, node.inVariable.name);
node = nodes[4];