Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

use data from indexes if possivle SERVER-192

  • Loading branch information...
commit 2603a9632c21f9e56e780f57b15313ed9d8810ff 1 parent 778d26e
Eliot Horowitz erh authored
Showing with 67 additions and 9 deletions.
  1. +5 −2 db/clientcursor.h
  2. +34 −7 db/query.cpp
  3. +28 −0 jstests/proj_key1.js
7 db/clientcursor.h
View
@@ -218,6 +218,9 @@ namespace mongo {
void setPos( int n ) { _pos = n; } // TODO : this is bad too
BSONObj indexKeyPattern() { return _c->indexKeyPattern(); }
+ bool modifiedKeys() const { return _c->modifiedKeys(); }
+ bool isMultiKey() const { return _c->isMultiKey(); }
+
bool ok() { return _c->ok(); }
bool advance(){ return _c->advance(); }
BSONObj current() { return _c->current(); }
@@ -354,8 +357,8 @@ namespace mongo {
ElapsedTracker _yieldSometimesTracker;
public:
- shared_ptr< ParsedQuery > pq;
- shared_ptr< Projection > fields; // which fields query wants returned
+ shared_ptr<ParsedQuery> pq;
+ shared_ptr<Projection> fields; // which fields query wants returned
Message originalMessage; // this is effectively an auto ptr for data the matcher points to
41 db/query.cpp
View
@@ -290,7 +290,7 @@ namespace mongo {
int resultFlags = ResultFlag_AwaitCapable;
int start = 0;
int n = 0;
-
+
if ( !cc ) {
log() << "getMore: cursorid not found " << ns << " " << cursorid << endl;
cursorid = 0;
@@ -312,6 +312,10 @@ namespace mongo {
c->checkLocation();
DiskLoc last;
+ scoped_ptr<Projection::KeyOnly> keyFieldsOnly;
+ if ( cc->modifiedKeys() == false && cc->isMultiKey() == false && cc->fields )
+ keyFieldsOnly.reset( cc->fields->checkKey( cc->indexKeyPattern() ) );
+
while ( 1 ) {
if ( !c->ok() ) {
if ( c->tailable() ) {
@@ -350,11 +354,17 @@ namespace mongo {
}
else {
last = c->currLoc();
- BSONObj js = c->current();
-
- // show disk loc should be part of the main query, not in an $or clause, so this should be ok
- fillQueryResultFromObj(b, cc->fields.get(), js, ( cc->pq.get() && cc->pq->showDiskLoc() ? &last : 0));
n++;
+
+ if ( keyFieldsOnly ){
+ fillQueryResultFromObj(b, 0, keyFieldsOnly->hydrate( c->currKey() ) );
+ }
+ else {
+ BSONObj js = c->current();
+ // show disk loc should be part of the main query, not in an $or clause, so this should be ok
+ fillQueryResultFromObj(b, cc->fields.get(), js, ( cc->pq.get() && cc->pq->showDiskLoc() ? &last : 0));
+ }
+
if ( ( ntoreturn && n >= ntoreturn ) || b.len() > MaxBytesToReturnToClientAtOnce ){
c->advance();
cc->incPos( n );
@@ -547,7 +557,8 @@ namespace mongo {
b << "cursor" << c->toString() << "indexBounds" << c->prettyIndexBounds();
b.done();
}
- void noteScan( Cursor *c, long long nscanned, long long nscannedObjects, int n, bool scanAndOrder, int millis, bool hint, int nYields , int nChunkSkips ) {
+ void noteScan( Cursor *c, long long nscanned, long long nscannedObjects, int n, bool scanAndOrder,
+ int millis, bool hint, int nYields , int nChunkSkips , bool indexOnly ) {
if ( _i == 1 ) {
_c.reset( new BSONArrayBuilder() );
*_c << _b->obj();
@@ -570,6 +581,7 @@ namespace mongo {
*_b << "nYields" << nYields;
*_b << "nChunkSkips" << nChunkSkips;
*_b << "isMultiKey" << c->isMultiKey();
+ *_b << "indexOnly" << indexOnly;
*_b << "indexBounds" << c->prettyIndexBounds();
@@ -640,6 +652,15 @@ namespace mongo {
} else {
_c = qp().newCursor( DiskLoc() , _pq.getNumToReturn() + _pq.getSkip() );
_capped = _c->capped();
+
+ cout << "ELIOT : " << _pq.getFields() << endl;
+
+ // setup check for if we can only use index to extract
+ if ( _c->modifiedKeys() == false && _c->isMultiKey() == false && _pq.getFields() ){
+ cout << "\t YO" << endl;
+ _keyFieldsOnly.reset( _pq.getFields()->checkKey( _c->indexKeyPattern() ) );
+ cout << "\t " << _keyFieldsOnly.get() << endl;
+ }
}
if ( qp().scanAndOrderRequired() ) {
@@ -763,6 +784,9 @@ namespace mongo {
bb.appendKeys( _c->indexKeyPattern() , _c->currKey() );
bb.done();
}
+ else if ( _keyFieldsOnly ){
+ fillQueryResultFromObj( _buf , 0 , _keyFieldsOnly->hydrate( _c->currKey() ) );
+ }
else {
BSONObj js = _c->current();
assert( js.isValid() );
@@ -824,7 +848,9 @@ namespace mongo {
}
if ( _pq.isExplain() ) {
- _eb.noteScan( _c.get(), _nscanned, _nscannedObjects, _n, scanAndOrderRequired(), _curop.elapsedMillis(), useHints && !_pq.getHint().eoo(), _nYields , _nChunkSkips);
+ _eb.noteScan( _c.get(), _nscanned, _nscannedObjects, _n, scanAndOrderRequired(),
+ _curop.elapsedMillis(), useHints && !_pq.getHint().eoo(), _nYields ,
+ _nChunkSkips, _keyFieldsOnly.get() > 0 );
}
else {
if ( _buf.len() ) {
@@ -883,6 +909,7 @@ namespace mongo {
private:
BufBuilder _buf;
const ParsedQuery& _pq;
+ scoped_ptr<Projection::KeyOnly> _keyFieldsOnly;
long long _ntoskip;
long long _nscanned;
28 jstests/proj_key1.js
View
@@ -0,0 +1,28 @@
+
+t = db.proj_key1;
+t.drop();
+
+as = []
+
+for ( i=0; i<10; i++ ){
+ as.push( { a : i } )
+ t.insert( { a : i , b : i } );
+}
+
+assert( ! t.find( {} , { a : 1 } ).explain().indexOnly , "A1" )
+
+t.ensureIndex( { a : 1 } )
+
+assert( t.find( { a : { $gte : 0 } } , { a : 1 , _id : 0 } ).explain().indexOnly , "A2" )
+
+assert( ! t.find( { a : { $gte : 0 } } , { a : 1 } ).explain().indexOnly , "A3" ) // because id _id
+
+// assert( t.find( {} , { a : 1 , _id : 0 } ).explain().indexOnly , "A4" ); // TODO: need to modify query optimier SERVER-2109
+
+assert.eq( as , t.find( { a : { $gte : 0 } } , { a : 1 , _id : 0 } ).toArray() , "B1" )
+assert.eq( as , t.find( { a : { $gte : 0 } } , { a : 1 , _id : 0 } ).batchSize(2).toArray() , "B1" )
+
+
+
+
+
Please sign in to comment.
Something went wrong with that request. Please try again.