summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Storch <david.storch@10gen.com>2015-01-13 17:26:54 -0500
committerDavid Storch <david.storch@10gen.com>2015-01-23 15:30:24 -0500
commit37ea3acc57d117ea6414c108b9c888083dbf2144 (patch)
tree01e8037c00dd86eaf729ad79662c2fea159a8a11
parent28b9b81eba5b79f1f83404d2220668fcbacd1aec (diff)
downloadmongo-37ea3acc57d117ea6414c108b9c888083dbf2144.tar.gz
SERVER-16527 S2NearStage explain correctly reports nscanned, nscannedObjects, and isMultiKey
-rw-r--r--src/mongo/db/exec/index_scan.cpp8
-rw-r--r--src/mongo/db/exec/index_scan.h10
-rw-r--r--src/mongo/db/exec/plan_stats.h13
-rw-r--r--src/mongo/db/exec/s2near.cpp35
-rw-r--r--src/mongo/db/exec/s2near.h9
-rw-r--r--src/mongo/db/query/explain_plan.cpp12
6 files changed, 67 insertions, 20 deletions
diff --git a/src/mongo/db/exec/index_scan.cpp b/src/mongo/db/exec/index_scan.cpp
index 062ba1b5162..2323b11102b 100644
--- a/src/mongo/db/exec/index_scan.cpp
+++ b/src/mongo/db/exec/index_scan.cpp
@@ -338,6 +338,14 @@ namespace mongo {
}
}
+ CommonStats* IndexScan::getCommonStats() {
+ return &_commonStats;
+ }
+
+ IndexScanStats* IndexScan::getSpecificStats() {
+ return &_specificStats;
+ }
+
PlanStageStats* IndexScan::getStats() {
// WARNING: this could be called even if the collection was dropped. Do not access any
// catalog information here.
diff --git a/src/mongo/db/exec/index_scan.h b/src/mongo/db/exec/index_scan.h
index 6d08f76b09a..d5bffbf7439 100644
--- a/src/mongo/db/exec/index_scan.h
+++ b/src/mongo/db/exec/index_scan.h
@@ -112,6 +112,16 @@ namespace mongo {
virtual PlanStageStats* getStats();
+ /**
+ * Get an unowned pointer to this stage's common stats.
+ */
+ CommonStats* getCommonStats();
+
+ /**
+ * Get an unowned pointer to this stage's specific stats.
+ */
+ IndexScanStats* getSpecificStats();
+
private:
/**
* Initialize the underlying IndexCursor, grab information from the catalog for stats.
diff --git a/src/mongo/db/exec/plan_stats.h b/src/mongo/db/exec/plan_stats.h
index 536b4d822ff..5266bf99491 100644
--- a/src/mongo/db/exec/plan_stats.h
+++ b/src/mongo/db/exec/plan_stats.h
@@ -349,6 +349,19 @@ namespace mongo {
size_t forcedFetches;
};
+ struct S2NearStats : public SpecificStats {
+ S2NearStats() : nscanned(0), nscannedObjects(0), isMultiKey(false) { }
+
+ virtual SpecificStats* clone() const {
+ S2NearStats* specific = new S2NearStats(*this);
+ return specific;
+ }
+
+ size_t nscanned;
+ size_t nscannedObjects;
+ bool isMultiKey;
+ };
+
struct ShardingFilterStats : public SpecificStats {
ShardingFilterStats() : chunkSkips(0) { }
diff --git a/src/mongo/db/exec/s2near.cpp b/src/mongo/db/exec/s2near.cpp
index 8ad0c2bd9eb..30770d4c22f 100644
--- a/src/mongo/db/exec/s2near.cpp
+++ b/src/mongo/db/exec/s2near.cpp
@@ -30,7 +30,6 @@
#include "mongo/db/client.h"
#include "mongo/db/catalog/database.h"
-#include "mongo/db/exec/fetch.h"
#include "mongo/db/exec/index_scan.h"
#include "mongo/db/exec/working_set_common.h"
#include "mongo/db/exec/working_set_computed_data.h"
@@ -40,12 +39,13 @@
namespace mongo {
- S2NearStage::S2NearStage(const S2NearParams& params, WorkingSet* ws) {
- _initted = false;
- _params = params;
- _ws = ws;
- _worked = false;
- _failed = false;
+ S2NearStage::S2NearStage(const S2NearParams& params, WorkingSet* ws)
+ : _worked(false),
+ _params(params),
+ _ws(ws),
+ _indexScan(NULL),
+ _failed(false),
+ _initted(false) {
}
void S2NearStage::init() {
@@ -278,10 +278,10 @@ namespace mongo {
// Owns geo filter.
_keyGeoFilter.reset(new GeoS2KeyMatchExpression(
&_annulus, _params.baseBounds.fields[_nearFieldIndex].name));
- IndexScan* scan = new IndexScan(params, _ws, _keyGeoFilter.get());
+ _indexScan = new IndexScan(params, _ws, _keyGeoFilter.get());
- // Owns 'scan'.
- _child.reset(new FetchStage(_ws, scan, _params.filter));
+ // Owns '_indexScan'.
+ _child.reset(new FetchStage(_ws, _indexScan, _params.filter));
_seenInScan.clear();
}
@@ -290,6 +290,15 @@ namespace mongo {
// All done reading from _child.
if (PlanStage::IS_EOF == state) {
+ // Aggregate stats from index scan used to get results for the annulus.
+ invariant(_indexScan);
+ _specificStats.nscanned += _indexScan->getSpecificStats()->keysExamined;
+ _specificStats.nscannedObjects += _indexScan->getCommonStats()->advanced;
+ if (_indexScan->getSpecificStats()->isMultiKey) {
+ _specificStats.isMultiKey = true;
+ }
+ _indexScan = NULL;
+
_child.reset();
_keyGeoFilter.reset();
@@ -426,10 +435,10 @@ namespace mongo {
}
PlanStageStats* S2NearStage::getStats() {
- // TODO: must agg stats across child ixscan/fetches.
- // TODO: we can do better than this, need own common stats.
_commonStats.isEOF = isEOF();
- return new PlanStageStats(_commonStats, STAGE_GEO_NEAR_2DSPHERE);
+ auto_ptr<PlanStageStats> ret(new PlanStageStats(_commonStats, STAGE_GEO_NEAR_2DSPHERE));
+ ret->specific.reset(new S2NearStats(_specificStats));
+ return ret.release();
}
} // namespace mongo
diff --git a/src/mongo/db/exec/s2near.h b/src/mongo/db/exec/s2near.h
index 054b4cce16f..9f9c1d07354 100644
--- a/src/mongo/db/exec/s2near.h
+++ b/src/mongo/db/exec/s2near.h
@@ -30,6 +30,8 @@
#include <queue>
+#include "mongo/db/exec/fetch.h"
+#include "mongo/db/exec/index_scan.h"
#include "mongo/db/exec/plan_stage.h"
#include "mongo/db/geo/geoquery.h"
#include "mongo/db/geo/s2common.h"
@@ -94,7 +96,11 @@ namespace mongo {
// Geo filter in index scan (which is owned by fetch stage in _child).
scoped_ptr<MatchExpression> _keyGeoFilter;
- scoped_ptr<PlanStage> _child;
+ // The child fetch stage for the current annulus.
+ scoped_ptr<FetchStage> _child;
+
+ // The child of '_child'. Not owned here.
+ IndexScan* _indexScan;
// The S2 machinery that represents the search annulus. We keep this around after bounds
// generation to check for intersection.
@@ -153,6 +159,7 @@ namespace mongo {
IndexDescriptor* _descriptor;
CommonStats _commonStats;
+ S2NearStats _specificStats;
};
} // namespace mongo
diff --git a/src/mongo/db/query/explain_plan.cpp b/src/mongo/db/query/explain_plan.cpp
index 750e770e14e..f9c24ecdee6 100644
--- a/src/mongo/db/query/explain_plan.cpp
+++ b/src/mongo/db/query/explain_plan.cpp
@@ -260,15 +260,15 @@ namespace mongo {
res->setIndexOnly(false);
}
else if (leaf->stageType == STAGE_GEO_NEAR_2DSPHERE) {
- // TODO: This is kind of a lie for STAGE_GEO_NEAR_2DSPHERE.
+ S2NearStats* s2stats = static_cast<S2NearStats*>(leaf->specific.get());
res->setCursor("S2NearCursor");
- // The first work() is an init. Every subsequent work examines a document.
- res->setNScanned(leaf->common.works);
- res->setNScannedObjects(leaf->common.works);
+
+ res->setNScanned(s2stats->nscanned);
+ res->setNScannedObjects(s2stats->nscannedObjects);
+
// TODO: only adding empty index bounds for backwards compatibility.
res->setIndexBounds(BSONObj());
- // TODO: Could be multikey.
- res->setIsMultiKey(false);
+ res->setIsMultiKey(s2stats->isMultiKey);
res->setIndexOnly(false);
}
else if (leaf->stageType == STAGE_GEO_NEAR_2D) {