Runner improvements

This commit is contained in:
Aaron
2009-02-25 10:48:41 -05:00
parent 9722627a02
commit 222ea643ad
4 changed files with 101 additions and 18 deletions

View File

@@ -142,37 +142,56 @@ namespace mongo {
}
QueryPlanSet::QueryPlanSet( const char *ns, const BSONObj &query, const BSONObj &order, const BSONElement *hint ) :
fbs_( ns, query ) {
fbs_( ns, query ),
mayRecordPlan_( true ),
usingPrerecordedPlan_( false ),
hint_( emptyObj ),
order_( order.copy() ) {
if ( hint && !hint->eoo() ) {
BSONObjBuilder b;
b.append( *hint );
hint_ = b.obj();
}
init();
}
void QueryPlanSet::init() {
mayRecordPlan_ = true;
usingPrerecordedPlan_ = false;
const char *ns = fbs_.ns();
NamespaceDetails *d = nsdetails( ns );
if ( !d || !fbs_.matchPossible() ) {
// Table scan plan, when no matches are possible
plans_.push_back( PlanPtr( new QueryPlan( fbs_, order ) ) );
plans_.push_back( PlanPtr( new QueryPlan( fbs_, order_ ) ) );
return;
}
if ( hint && !hint->eoo() ) {
if( hint->type() == String ) {
string hintstr = hint->valuestr();
BSONElement hint = hint_.firstElement();
if ( !hint.eoo() ) {
mayRecordPlan_ = false;
if( hint.type() == String ) {
string hintstr = hint.valuestr();
for (int i = 0; i < d->nIndexes; i++ ) {
IndexDetails& ii = d->indexes[i];
if ( ii.indexName() == hintstr ) {
plans_.push_back( PlanPtr( new QueryPlan( fbs_, order, &ii ) ) );
plans_.push_back( PlanPtr( new QueryPlan( fbs_, order_, &ii ) ) );
return;
}
}
}
else if( hint->type() == Object ) {
BSONObj hintobj = hint->embeddedObject();
else if( hint.type() == Object ) {
BSONObj hintobj = hint.embeddedObject();
uassert( "bad hint", !hintobj.isEmpty() );
if ( !strcmp( hintobj.firstElement().fieldName(), "$natural" ) ) {
// Table scan plan
plans_.push_back( PlanPtr( new QueryPlan( fbs_, order ) ) );
plans_.push_back( PlanPtr( new QueryPlan( fbs_, order_ ) ) );
return;
}
for (int i = 0; i < d->nIndexes; i++ ) {
IndexDetails& ii = d->indexes[i];
if( ii.keyPattern().woCompare(hintobj) == 0 ) {
plans_.push_back( PlanPtr( new QueryPlan( fbs_, order, &ii ) ) );
plans_.push_back( PlanPtr( new QueryPlan( fbs_, order_, &ii ) ) );
return;
}
}
@@ -182,34 +201,36 @@ namespace mongo {
BSONObj bestIndex = indexForPattern( ns, fbs_.pattern() );
if ( !bestIndex.isEmpty() ) {
usingPrerecordedPlan_ = true;
if ( !strcmp( bestIndex.firstElement().fieldName(), "$natural" ) ) {
// Table scan plan
plans_.push_back( PlanPtr( new QueryPlan( fbs_, order ) ) );
plans_.push_back( PlanPtr( new QueryPlan( fbs_, order_ ) ) );
return;
}
for (int i = 0; i < d->nIndexes; i++ ) {
IndexDetails& ii = d->indexes[i];
if( ii.keyPattern().woCompare(bestIndex) == 0 ) {
plans_.push_back( PlanPtr( new QueryPlan( fbs_, order, &ii ) ) );
plans_.push_back( PlanPtr( new QueryPlan( fbs_, order_, &ii ) ) );
return;
}
}
assert( false );
}
// Table scan plan
plans_.push_back( PlanPtr( new QueryPlan( fbs_, order ) ) );
plans_.push_back( PlanPtr( new QueryPlan( fbs_, order_ ) ) );
// If table scan is optimal
if ( fbs_.nNontrivialBounds() == 0 && order.isEmpty() )
if ( fbs_.nNontrivialBounds() == 0 && order_.isEmpty() )
return;
// Only table scan can give natural order.
if ( !order.isEmpty() && !strcmp( order.firstElement().fieldName(), "$natural" ) )
if ( !order_.isEmpty() && !strcmp( order_.firstElement().fieldName(), "$natural" ) )
return;
PlanSet plans;
for( int i = 0; i < d->nIndexes; ++i ) {
PlanPtr p( new QueryPlan( fbs_, order, &d->indexes[ i ] ) );
PlanPtr p( new QueryPlan( fbs_, order_, &d->indexes[ i ] ) );
if ( p->optimal() ) {
plans_.push_back( p );
return;
@@ -222,6 +243,14 @@ namespace mongo {
}
shared_ptr< QueryOp > QueryPlanSet::runOp( QueryOp &op ) {
if ( usingPrerecordedPlan_ ) {
Runner r( *this, op );
shared_ptr< QueryOp > res = r.run();
if ( res->complete() )
return res;
registerIndexForPattern( fbs_.ns(), fbs_.pattern(), BSONObj() );
init();
}
Runner r( *this, op );
return r.run();
}
@@ -257,7 +286,7 @@ namespace mongo {
op.setExceptionMessage( "Caught unknown exception" );
}
if ( op.complete() ) {
if ( op.mayRecordPlan() )
if ( plans_.mayRecordPlan_ && op.mayRecordPlan() )
op.qp().registerSelf();
return *i;
}