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:
parent
b66a139b17
commit
719e23b5f7
@ -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() ) {
|
||||
|
@ -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() );
|
||||
|
||||
|
@ -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 ) {
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user