Move index cache to NamespaceDetailsTransient

This commit is contained in:
Aaron
2009-03-03 17:30:26 -05:00
parent 72a7d08cd4
commit 2ba030abe0
8 changed files with 43 additions and 48 deletions

View File

@@ -506,7 +506,7 @@ namespace mongo {
typedef map< string, shared_ptr< NamespaceDetailsTransient > >::iterator ouriter;
void NamespaceDetailsTransient::reset() {
clearQueryCache( ns.c_str() );
clearQueryCache();
haveIndexKeys = false;
}

View File

@@ -21,6 +21,7 @@
#include "../stdafx.h"
#include "jsobj.h"
#include "queryutil.h"
#include "storage.h"
#include "../util/hashtab.h"
@@ -343,8 +344,10 @@ namespace mongo {
bool haveIndexKeys;
set<string> allIndexKeys;
void computeIndexKeys();
int writeCount_;
map< QueryPattern, pair< BSONObj, int > > queryCache_;
public:
NamespaceDetailsTransient(const char *_ns) : ns(_ns) {
NamespaceDetailsTransient(const char *_ns) : ns(_ns), haveIndexKeys(), writeCount_() {
haveIndexKeys=false; /*lazy load them*/
}
~NamespaceDetailsTransient() { reset(); }
@@ -362,6 +365,25 @@ namespace mongo {
void addedIndex() { reset(); }
void deletedIndex() { reset(); }
void registerWriteOp() {
if ( queryCache_.empty() )
return;
if ( ++writeCount_ >= 100 )
clearQueryCache();
}
void clearQueryCache() {
queryCache_.clear();
writeCount_ = 0;
}
BSONObj indexForPattern( const QueryPattern &pattern ) {
return queryCache_[ pattern ].first;
}
int nScannedForPattern( const QueryPattern &pattern ) {
return queryCache_[ pattern ].second;
}
void registerIndexForPattern( const QueryPattern &pattern, const BSONObj &indexKey, int nScanned ) {
queryCache_[ pattern ] = make_pair( indexKey, nScanned );
}
private:
void reset();
static std::map< string, shared_ptr< NamespaceDetailsTransient > > map;

View File

@@ -772,7 +772,7 @@ assert( !eloc.isNull() );
unindexRecord(ns, d, todelete, dl);
_deleteRecord(d, ns, todelete, dl);
registerWriteOp( ns );
NamespaceDetailsTransient::get( ns ).registerWriteOp();
}
void setDifference(BSONObjSetDefaultOrder &l, BSONObjSetDefaultOrder &r, vector<BSONObj*> &diff) {
@@ -849,7 +849,7 @@ assert( !eloc.isNull() );
return;
}
registerWriteOp( ns );
NamespaceDetailsTransient::get( ns ).registerWriteOp();
d->paddingFits();
/* has any index keys changed? */
@@ -1208,7 +1208,7 @@ assert( !eloc.isNull() );
d->datasize += r->netLength();
if ( !god )
registerWriteOp( ns );
NamespaceDetailsTransient::get( ns ).registerWriteOp();
if ( tableToIndex ) {
IndexDetails& idxinfo = tableToIndex->indexes[tableToIndex->nIndexes];

View File

@@ -141,6 +141,10 @@ namespace mongo {
return index_->keyPattern();
}
void QueryPlan::registerSelf( int nScanned ) const {
NamespaceDetailsTransient::get( ns() ).registerIndexForPattern( fbs_.pattern( order_ ), indexKey(), nScanned );
}
QueryPlanSet::QueryPlanSet( const char *ns, const BSONObj &query, const BSONObj &order, const BSONElement *hint, bool honorRecordedPlan ) :
fbs_( ns, query ),
mayRecordPlan_( true ),
@@ -203,11 +207,11 @@ namespace mongo {
}
if ( honorRecordedPlan_ ) {
BSONObj bestIndex = indexForPattern( ns, fbs_.pattern( order_ ) );
BSONObj bestIndex = NamespaceDetailsTransient::get( ns ).indexForPattern( fbs_.pattern( order_ ) );
if ( !bestIndex.isEmpty() ) {
usingPrerecordedPlan_ = true;
mayRecordPlan_ = false;
oldNScanned_ = nScannedForPattern( ns, fbs_.pattern( order_ ) );
oldNScanned_ = NamespaceDetailsTransient::get( ns ).nScannedForPattern( fbs_.pattern( order_ ) );
if ( !strcmp( bestIndex.firstElement().fieldName(), "$natural" ) ) {
// Table scan plan
plans_.push_back( PlanPtr( new QueryPlan( fbs_, order_ ) ) );
@@ -275,7 +279,7 @@ namespace mongo {
// plans_.size() > 1 if addOtherPlans was called in Runner::run().
if ( res->complete() || plans_.size() > 1 )
return res;
registerIndexForPattern( fbs_.ns(), fbs_.pattern( order_ ), BSONObj(), 0 );
NamespaceDetailsTransient::get( fbs_.ns() ).registerIndexForPattern( fbs_.pattern( order_ ), BSONObj(), 0 );
init();
}
Runner r( *this, op );

View File

@@ -50,9 +50,7 @@ namespace mongo {
const char *ns() const { return fbs_.ns(); }
BSONObj query() const { return fbs_.query(); }
const FieldBound &bound( const char *fieldName ) const { return fbs_.bound( fieldName ); }
void registerSelf( int nScanned ) const {
registerIndexForPattern( ns(), fbs_.pattern( order_ ), indexKey(), nScanned );
}
void registerSelf( int nScanned ) const;
private:
const FieldBoundSet &fbs_;
const BSONObj &order_;

View File

@@ -24,28 +24,6 @@
namespace mongo {
map< string, int > writeCount_;
map< string, map< QueryPattern, pair< BSONObj, int > > > queryCache_;
void registerWriteOp( const string &ns ) {
if ( queryCache_[ ns ].empty() )
return;
if ( ++writeCount_[ ns ] >= 100 )
clearQueryCache( ns );
}
void clearQueryCache( const string &ns ) {
queryCache_[ ns ].clear();
writeCount_[ ns ] = 0;
}
BSONObj indexForPattern( const string &ns, const QueryPattern &pattern ) {
return queryCache_[ ns ][ pattern ].first;
}
int nScannedForPattern( const string &ns, const QueryPattern &pattern ) {
return queryCache_[ ns ][ pattern ].second;
}
void registerIndexForPattern( const string &ns, const QueryPattern &pattern, const BSONObj &indexKey, int nScanned ) {
queryCache_[ ns ][ pattern ] = make_pair( indexKey, nScanned );
}
FieldBound::FieldBound( const BSONElement &e ) :
lower_( minKey.firstElement() ),
lowerInclusive_( true ),

View File

@@ -22,13 +22,6 @@
namespace mongo {
class QueryPattern;
void registerWriteOp( const string &ns );
void clearQueryCache( const string &ns );
BSONObj indexForPattern( const string &ns, const QueryPattern &pattern );
int nScannedForPattern( const string &ns, const QueryPattern &pattern );
void registerIndexForPattern( const string &ns, const QueryPattern &pattern, const BSONObj &indexKey, int nScanned );
class FieldBound {
public:
FieldBound( const BSONElement &e = emptyObj.firstElement() );

View File

@@ -512,7 +512,7 @@ namespace QueryOptimizerTests {
~Base() {
if ( !nsd() )
return;
clearQueryCache( ns() );
NamespaceDetailsTransient::get( ns() ).clearQueryCache();
string s( ns() );
dropNS( s );
}
@@ -823,8 +823,8 @@ namespace QueryOptimizerTests {
QueryPlanSet s( ns(), BSON( "a" << 4 ), BSON( "b" << 1 ) );
ScanOnlyTestOp op;
s.runOp( op );
ASSERT( fromjson( "{$natural:1}" ).woCompare( indexForPattern( ns(), s.fbs().pattern( BSON( "b" << 1 ) ) ) ) == 0 );
ASSERT_EQUALS( 1, nScannedForPattern( ns(), s.fbs().pattern( BSON( "b" << 1 ) ) ) );
ASSERT( fromjson( "{$natural:1}" ).woCompare( NamespaceDetailsTransient::get( ns() ).indexForPattern( s.fbs().pattern( BSON( "b" << 1 ) ) ) ) == 0 );
ASSERT_EQUALS( 1, NamespaceDetailsTransient::get( ns() ).nScannedForPattern( s.fbs().pattern( BSON( "b" << 1 ) ) ) );
QueryPlanSet s2( ns(), BSON( "a" << 4 ), BSON( "b" << 1 ) );
TestOp op2;
@@ -880,8 +880,8 @@ namespace QueryOptimizerTests {
BSONObj one = BSON( "a" << 1 );
theDataFileMgr.insert( ns(), one );
deleteObjects( ns(), BSON( "a" << 1 ), false );
ASSERT( BSON( "a" << 1 ).woCompare( indexForPattern( ns(), FieldBoundSet( ns(), BSON( "a" << 1 ) ).pattern() ) ) == 0 );
ASSERT_EQUALS( 2, nScannedForPattern( ns(), FieldBoundSet( ns(), BSON( "a" << 1 ) ).pattern() ) );
ASSERT( BSON( "a" << 1 ).woCompare( NamespaceDetailsTransient::get( ns() ).indexForPattern( FieldBoundSet( ns(), BSON( "a" << 1 ) ).pattern() ) ) == 0 );
ASSERT_EQUALS( 2, NamespaceDetailsTransient::get( ns() ).nScannedForPattern( FieldBoundSet( ns(), BSON( "a" << 1 ) ).pattern() ) );
}
};
@@ -932,13 +932,13 @@ namespace QueryOptimizerTests {
assembleRequest( ns(), QUERY( "b" << 0 << "a" << GTE << 0 ).obj, 2, 0, 0, 0, m );
stringstream ss;
runQuery( m, ss );
ASSERT( BSON( "$natural" << 1 ).woCompare( indexForPattern( ns(), FieldBoundSet( ns(), BSON( "b" << 0 << "a" << GTE << 0 ) ).pattern() ) ) == 0 );
ASSERT( BSON( "$natural" << 1 ).woCompare( NamespaceDetailsTransient::get( ns() ).indexForPattern( FieldBoundSet( ns(), BSON( "b" << 0 << "a" << GTE << 0 ) ).pattern() ) ) == 0 );
Message m2;
assembleRequest( ns(), QUERY( "b" << 99 << "a" << GTE << 0 ).obj, 2, 0, 0, 0, m2 );
runQuery( m2, ss );
ASSERT( BSON( "a" << 1 ).woCompare( indexForPattern( ns(), FieldBoundSet( ns(), BSON( "b" << 0 << "a" << GTE << 0 ) ).pattern() ) ) == 0 );
ASSERT_EQUALS( 2, nScannedForPattern( ns(), FieldBoundSet( ns(), BSON( "b" << 0 << "a" << GTE << 0 ) ).pattern() ) );
ASSERT( BSON( "a" << 1 ).woCompare( NamespaceDetailsTransient::get( ns() ).indexForPattern( FieldBoundSet( ns(), BSON( "b" << 0 << "a" << GTE << 0 ) ).pattern() ) ) == 0 );
ASSERT_EQUALS( 2, NamespaceDetailsTransient::get( ns() ).nScannedForPattern( FieldBoundSet( ns(), BSON( "b" << 0 << "a" << GTE << 0 ) ).pattern() ) );
}
};