Move index cache to NamespaceDetailsTransient
This commit is contained in:
@@ -506,7 +506,7 @@ namespace mongo {
|
||||
typedef map< string, shared_ptr< NamespaceDetailsTransient > >::iterator ouriter;
|
||||
|
||||
void NamespaceDetailsTransient::reset() {
|
||||
clearQueryCache( ns.c_str() );
|
||||
clearQueryCache();
|
||||
haveIndexKeys = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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 ),
|
||||
|
||||
@@ -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() );
|
||||
|
||||
@@ -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() ) );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user