diff options
author | David Storch <david.storch@10gen.com> | 2015-01-13 17:26:54 -0500 |
---|---|---|
committer | David Storch <david.storch@10gen.com> | 2015-01-23 15:30:24 -0500 |
commit | 37ea3acc57d117ea6414c108b9c888083dbf2144 (patch) | |
tree | 01e8037c00dd86eaf729ad79662c2fea159a8a11 | |
parent | 28b9b81eba5b79f1f83404d2220668fcbacd1aec (diff) | |
download | mongo-37ea3acc57d117ea6414c108b9c888083dbf2144.tar.gz |
SERVER-16527 S2NearStage explain correctly reports nscanned, nscannedObjects, and isMultiKey
-rw-r--r-- | src/mongo/db/exec/index_scan.cpp | 8 | ||||
-rw-r--r-- | src/mongo/db/exec/index_scan.h | 10 | ||||
-rw-r--r-- | src/mongo/db/exec/plan_stats.h | 13 | ||||
-rw-r--r-- | src/mongo/db/exec/s2near.cpp | 35 | ||||
-rw-r--r-- | src/mongo/db/exec/s2near.h | 9 | ||||
-rw-r--r-- | src/mongo/db/query/explain_plan.cpp | 12 |
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) { |