From 2ba030abe039dadc3f2c4bebfcb671fcab950d03 Mon Sep 17 00:00:00 2001 From: Aaron Date: Tue, 3 Mar 2009 17:30:26 -0500 Subject: [PATCH] Move index cache to NamespaceDetailsTransient --- db/namespace.cpp | 2 +- db/namespace.h | 24 +++++++++++++++++++++++- db/pdfile.cpp | 6 +++--- db/queryoptimizer.cpp | 10 +++++++--- db/queryoptimizer.h | 4 +--- db/queryutil.cpp | 22 ---------------------- db/queryutil.h | 7 ------- dbtests/queryoptimizertests.cpp | 16 ++++++++-------- 8 files changed, 43 insertions(+), 48 deletions(-) diff --git a/db/namespace.cpp b/db/namespace.cpp index 630dfa38a8f..521c64e21a1 100644 --- a/db/namespace.cpp +++ b/db/namespace.cpp @@ -506,7 +506,7 @@ namespace mongo { typedef map< string, shared_ptr< NamespaceDetailsTransient > >::iterator ouriter; void NamespaceDetailsTransient::reset() { - clearQueryCache( ns.c_str() ); + clearQueryCache(); haveIndexKeys = false; } diff --git a/db/namespace.h b/db/namespace.h index 991d1d62dcf..8ca24c8ea71 100644 --- a/db/namespace.h +++ b/db/namespace.h @@ -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 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; diff --git a/db/pdfile.cpp b/db/pdfile.cpp index 8e14c1226c1..da909b8f6bb 100644 --- a/db/pdfile.cpp +++ b/db/pdfile.cpp @@ -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 &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]; diff --git a/db/queryoptimizer.cpp b/db/queryoptimizer.cpp index 8d3845b9f31..25a123eacac 100644 --- a/db/queryoptimizer.cpp +++ b/db/queryoptimizer.cpp @@ -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 ); diff --git a/db/queryoptimizer.h b/db/queryoptimizer.h index e69d4b5d0cc..66c08917749 100644 --- a/db/queryoptimizer.h +++ b/db/queryoptimizer.h @@ -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_; diff --git a/db/queryutil.cpp b/db/queryutil.cpp index e8693df0d67..64afe9ac464 100644 --- a/db/queryutil.cpp +++ b/db/queryutil.cpp @@ -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 ), diff --git a/db/queryutil.h b/db/queryutil.h index 4c8baf9cf34..323bfd8c788 100644 --- a/db/queryutil.h +++ b/db/queryutil.h @@ -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() ); diff --git a/dbtests/queryoptimizertests.cpp b/dbtests/queryoptimizertests.cpp index 09b1ceb4fd6..27deaf248ee 100644 --- a/dbtests/queryoptimizertests.cpp +++ b/dbtests/queryoptimizertests.cpp @@ -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() ) ); } };