0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-12-01 09:32:32 +01:00

SERVER-2977 add nscanned to query optimizer cursor

This commit is contained in:
Aaron 2011-05-17 19:08:24 -07:00
parent b66a139b17
commit 719e23b5f7
4 changed files with 53 additions and 12 deletions

View File

@ -964,8 +964,8 @@ doneCheckOrder:
}
}
MultiCursor::MultiCursor( auto_ptr<MultiPlanScanner> mps, const shared_ptr<Cursor> &c, const shared_ptr<CoveredIndexMatcher> &matcher, const QueryOp &op )
: _op( new NoOp( op ) ), _c( c ), _mps( mps ), _matcher( matcher ), _nscanned( -1 ) {
MultiCursor::MultiCursor( auto_ptr<MultiPlanScanner> mps, const shared_ptr<Cursor> &c, const shared_ptr<CoveredIndexMatcher> &matcher, const QueryOp &op, long long nscanned )
: _op( new NoOp( op ) ), _c( c ), _mps( mps ), _matcher( matcher ), _nscanned( nscanned ) {
_mps->setBestGuessOnly();
_mps->mayYield( false ); // with a NoOp, there's no need to yield in QueryPlanSet
if ( !ok() ) {

View File

@ -428,8 +428,14 @@ namespace mongo {
};
/** takes ownership of 'op' */
MultiCursor( const char *ns, const BSONObj &pattern, const BSONObj &order, shared_ptr<CursorOp> op = shared_ptr<CursorOp>(), bool mayYield = false );
/** used to handoff a query to a getMore() */
MultiCursor( auto_ptr<MultiPlanScanner> mps, const shared_ptr<Cursor> &c, const shared_ptr<CoveredIndexMatcher> &matcher, const QueryOp &op );
/**
* Used
* 1. To handoff a query to a getMore()
* 2. To handoff a QueryOptimizerCursor
* @param nscanned is an optional initial value, if not supplied nscanned()
* will always return -1
*/
MultiCursor( auto_ptr<MultiPlanScanner> mps, const shared_ptr<Cursor> &c, const shared_ptr<CoveredIndexMatcher> &matcher, const QueryOp &op, long long nscanned = -1 );
virtual bool ok() { return _c->ok(); }
virtual Record* _current() { return _c->_current(); }
@ -517,7 +523,7 @@ namespace mongo {
*
* This is a work in progress. Partial list of features not yet implemented:
* - modification of scanned documents
* - stats like nscanned
* - covered indexes
*/
shared_ptr<Cursor> newQueryOptimizerCursor( const char *ns, const BSONObj &query, const BSONObj &order = BSONObj() );

View File

@ -25,7 +25,7 @@ namespace mongo {
class QueryOptimizerCursorOp : public QueryOp {
public:
QueryOptimizerCursorOp() : _matchCount(), _mustAdvance(), _nscanned() {}
QueryOptimizerCursorOp( long long &aggregateNscanned ) : _matchCount(), _mustAdvance(), _nscanned(), _aggregateNscanned( aggregateNscanned ) {}
virtual void _init() {
if ( qp().scanAndOrderRequired() ) {
@ -33,6 +33,7 @@ namespace mongo {
}
_c = qp().newCursor();
_capped = _c->capped();
mayAdvance();
}
virtual long long nscanned() {
@ -86,14 +87,13 @@ namespace mongo {
return;
}
_nscanned = _c->nscanned();
if ( matcher( _c )->matchesCurrent( _c.get() ) && !_c->getsetdup( _c->currLoc() ) ) {
++_matchCount;
}
_mustAdvance = true;
}
virtual QueryOp *_createChild() const {
QueryOptimizerCursorOp *ret = new QueryOptimizerCursorOp();
QueryOptimizerCursorOp *ret = new QueryOptimizerCursorOp( _aggregateNscanned );
ret->_matchCount = _matchCount;
return ret;
}
@ -109,6 +109,8 @@ namespace mongo {
_c->advance();
_mustAdvance = false;
}
_aggregateNscanned += ( _c->nscanned() - _nscanned );
_nscanned = _c->nscanned();
}
int _matchCount;
bool _mustAdvance;
@ -118,14 +120,16 @@ namespace mongo {
ClientCursor::CleanupPointer _cc;
DiskLoc _posBeforeYield;
ClientCursor::YieldData _yieldData;
long long &_aggregateNscanned;
};
class QueryOptimizerCursor : public Cursor {
public:
QueryOptimizerCursor( const char *ns, const BSONObj &query, const BSONObj &order ):
_mps( new MultiPlanScanner( ns, query, order ) ), // mayYield == false
_originalOp( new QueryOptimizerCursorOp() ),
_currOp() {
_originalOp( new QueryOptimizerCursorOp( _nscanned ) ),
_currOp(),
_nscanned() {
_mps->initialOp( _originalOp );
shared_ptr<QueryOp> op = _mps->nextOp();
rethrowOnError( op );
@ -168,7 +172,11 @@ namespace mongo {
}
else if ( op->stopRequested() ) {
if ( qocop->cursor() ) {
_takeover.reset( new MultiCursor( _mps, qocop->cursor(), op->matcher( qocop->cursor() ), *op ) );
_takeover.reset( new MultiCursor( _mps,
qocop->cursor(),
op->matcher( qocop->cursor() ),
*op,
_nscanned - qocop->cursor()->nscanned() ) );
}
}
@ -229,7 +237,7 @@ namespace mongo {
virtual bool modifiedKeys() const { return true; }
virtual long long nscanned() { return -1; }
virtual long long nscanned() { return _takeover ? _takeover->nscanned() : _nscanned; }
virtual shared_ptr< CoveredIndexMatcher > matcherPtr() const {
assertOk();
@ -267,6 +275,7 @@ namespace mongo {
QueryOptimizerCursorOp *_currOp;
set<DiskLoc> _dups;
shared_ptr<Cursor> _takeover;
long long _nscanned;
};
shared_ptr<Cursor> newQueryOptimizerCursor( const char *ns, const BSONObj &query, const BSONObj &order ) {

View File

@ -1008,6 +1008,7 @@ namespace QueryOptimizerTests {
}
}
shared_ptr<Cursor> c() { return _c; }
long long nscanned() const { return _c->nscanned(); }
private:
shared_ptr<Cursor> _c;
};
@ -2398,6 +2399,30 @@ namespace QueryOptimizerTests {
}
};
class Nscanned : public Base {
public:
void run() {
for( int i = 0; i < 120; ++i ) {
_cli.insert( ns(), BSON( "_id" << i << "a" << i ) );
}
dblock lk;
Client::Context ctx( ns() );
shared_ptr<Cursor> c = newQueryOptimizerCursor( ns(), BSON( "_id" << GTE << 0 << "a" << GTE << 0 ) );
ASSERT( c->ok() );
ASSERT_EQUALS( 2, c->nscanned() );
c->advance();
ASSERT( c->ok() );
ASSERT_EQUALS( 2, c->nscanned() );
c->advance();
for( int i = 3; i < 222; ++i ) {
ASSERT( c->ok() );
c->advance();
}
ASSERT( !c->ok() );
}
};
} // namespace QueryOptimizerCursorTests
class All : public Suite {
@ -2499,6 +2524,7 @@ namespace QueryOptimizerTests {
add<QueryOptimizerCursorTests::RecordedOrderInvalid>();
add<QueryOptimizerCursorTests::KillOp>();
add<QueryOptimizerCursorTests::KillOpFirstClause>();
add<QueryOptimizerCursorTests::Nscanned>();
}
} myall;