Skip to content

Commit c7d800c

Browse files
committed
SERVER-6718 new parameter to control replication index prefetching behavior
New parameter replIndexPrefetch. Settable via the command line or use setParameter() command on a running server. Only valid on a server started with --replSet parameter. This allows a user to disable the prefetching of all index pages prior to the application of a replicated op on a secondary. For most use cases, prefetching all indexes for a given op will provide good performance. For use cases that do many in-place updates to documents in a collection with many indexes that are unaffected by such updates, using the '_id_only' setting may provide better performance than the 'all' setting. The '_id_only' setting only prefetches index pages for the _id index, which will always be used to find the document needed to be updated. The 'none' setting will be used for debugging only; there should be no production use cases for this setting. getParameter() supports getting the current value of this parameter.
1 parent c879a4c commit c7d800c

File tree

8 files changed

+127
-9
lines changed

8 files changed

+127
-9
lines changed

src/mongo/db/cmdline.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ namespace mongo {
6868
}
6969
bool usingReplSets() const { return !_replSet.empty(); }
7070

71+
string rsIndexPrefetch;// --indexPrefetch
72+
7173
// for master/slave replication
7274
string source; // --source
7375
string only; // --only

src/mongo/db/db.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,7 @@ static int mongoDbMain(int argc, char* argv[]) {
701701

702702
rs_options.add_options()
703703
("replSet", po::value<string>(), "arg is <setname>[/<optionalseedhostlist>]")
704+
("replIndexPrefetch", po::value<string>(), "specify index prefetching behavior (if secondary) [none|_id_only|all]")
704705
;
705706

706707
sharding_options.add_options()
@@ -959,6 +960,9 @@ static int mongoDbMain(int argc, char* argv[]) {
959960
/* seed list of hosts for the repl set */
960961
cmdLine._replSet = params["replSet"].as<string>().c_str();
961962
}
963+
if (params.count("replIndexPrefetch")) {
964+
cmdLine.rsIndexPrefetch = params["replIndexPrefetch"].as<std::string>();
965+
}
962966
if (params.count("only")) {
963967
cmdLine.only = params["only"].as<string>().c_str();
964968
}

src/mongo/db/dbcommands.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,46 @@ namespace mongo {
6666
dur::setAgeOutJournalFiles(r);
6767
return true;
6868
}
69+
if( cmdObj.hasElement( "replIndexPrefetch" ) ) {
70+
if (!theReplSet) {
71+
errmsg = "replication is not enabled";
72+
return false;
73+
}
74+
std::string prefetch = cmdObj["replIndexPrefetch"].valuestrsafe();
75+
log() << "changing replication index prefetch behavior to " << prefetch << endl;
76+
// default:
77+
ReplSetImpl::IndexPrefetchConfig prefetchConfig = ReplSetImpl::PREFETCH_ALL;
78+
if (prefetch == "none")
79+
prefetchConfig = ReplSetImpl::PREFETCH_NONE;
80+
else if (prefetch == "_id_only")
81+
prefetchConfig = ReplSetImpl::PREFETCH_ID_ONLY;
82+
else if (prefetch == "all")
83+
prefetchConfig = ReplSetImpl::PREFETCH_ALL;
84+
else {
85+
warning() << "unrecognized indexPrefetch setting: " << prefetch << endl;
86+
}
87+
theReplSet->setIndexPrefetchConfig(prefetchConfig);
88+
return true;
89+
}
90+
6991
return false;
7092
}
7193

94+
const char* fetchReplIndexPrefetchParam() {
95+
if (!theReplSet) return "uninitialized";
96+
ReplSetImpl::IndexPrefetchConfig ip = theReplSet->getIndexPrefetchConfig();
97+
switch (ip) {
98+
case ReplSetImpl::PREFETCH_NONE:
99+
return "none";
100+
case ReplSetImpl::PREFETCH_ID_ONLY:
101+
return "_id_only";
102+
case ReplSetImpl::PREFETCH_ALL:
103+
return "all";
104+
default:
105+
return "invalid";
106+
}
107+
}
108+
72109
/* reset any errors so that getlasterror comes back clean.
73110
74111
useful before performing a long series of operations where we want to

src/mongo/db/dbcommands_generic.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ namespace mongo {
124124
*/
125125
unsigned replApplyBatchSize = 1;
126126

127+
const char* fetchReplIndexPrefetchParam();
128+
127129
class CmdGet : public Command {
128130
public:
129131
CmdGet() : Command( "getParameter" ) { }
@@ -160,7 +162,9 @@ namespace mongo {
160162
if( all || cmdObj.hasElement("replApplyBatchSize") ) {
161163
result.append("replApplyBatchSize", replApplyBatchSize);
162164
}
163-
165+
if (all || cmdObj.hasElement("replIndexPrefetch")) {
166+
result.append("replIndexPrefetch", fetchReplIndexPrefetchParam());
167+
}
164168
if ( before == result.len() ) {
165169
errmsg = "no option found to get";
166170
return false;

src/mongo/db/prefetch.cpp

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "mongo/db/index_update.h"
2525
#include "mongo/db/jsobj.h"
2626
#include "mongo/db/namespace_details.h"
27+
#include "mongo/db/repl/rs.h"
2728

2829
namespace mongo {
2930

@@ -67,23 +68,58 @@ namespace mongo {
6768
void prefetchIndexPages(NamespaceDetails *nsd, const BSONObj& obj) {
6869
DiskLoc unusedDl; // unused
6970
IndexInterface::IndexInserter inserter;
70-
71-
// includes all indexes, including ones
72-
// in the process of being built
73-
int indexCount = nsd->nIndexesBeingBuilt();
7471
BSONObjSet unusedKeys;
75-
for ( int indexNo = 0; indexNo < indexCount; indexNo++ ) {
76-
// This will page in all index pages for the given object.
72+
ReplSetImpl::IndexPrefetchConfig prefetchConfig = theReplSet->getIndexPrefetchConfig();
73+
switch (prefetchConfig) {
74+
case ReplSetImpl::PREFETCH_NONE:
75+
return;
76+
case ReplSetImpl::PREFETCH_ID_ONLY:
77+
{
78+
int indexNo = nsd->findIdIndex();
79+
if (indexNo == -1) return;
7780
try {
78-
fetchIndexInserters(/*out*/unusedKeys, inserter, nsd, indexNo, obj, unusedDl, /*allowDups*/true);
81+
fetchIndexInserters(/*out*/unusedKeys,
82+
inserter,
83+
nsd,
84+
indexNo,
85+
obj,
86+
unusedDl,
87+
/*allowDups*/true);
7988
}
8089
catch (const DBException& e) {
8190
LOG(2) << "ignoring exception in prefetchIndexPages(): " << e.what() << endl;
8291
}
83-
unusedKeys.clear();
92+
break;
93+
}
94+
case ReplSetImpl::PREFETCH_ALL:
95+
{
96+
// indexCount includes all indexes, including ones
97+
// in the process of being built
98+
int indexCount = nsd->nIndexesBeingBuilt();
99+
for ( int indexNo = 0; indexNo < indexCount; indexNo++ ) {
100+
// This will page in all index pages for the given object.
101+
try {
102+
fetchIndexInserters(/*out*/unusedKeys,
103+
inserter,
104+
nsd,
105+
indexNo,
106+
obj,
107+
unusedDl,
108+
/*allowDups*/true);
109+
}
110+
catch (const DBException& e) {
111+
LOG(2) << "ignoring exception in prefetchIndexPages(): " << e.what() << endl;
112+
}
113+
unusedKeys.clear();
114+
}
115+
break;
116+
}
117+
default:
118+
fassertFailed(16427);
84119
}
85120
}
86121

122+
87123
void prefetchRecordPages(const char* ns, const BSONObj& obj) {
88124
BSONElement _id;
89125
if( obj.getObjectID(_id) ) {

src/mongo/db/repl/rs.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,21 @@ namespace mongo {
397397
log() << "replSet warning command line seed " << i->toString() << " is not present in the current repl set config" << rsLog;
398398
}
399399
}
400+
401+
// Figure out indexPrefetch setting
402+
std::string& prefetch = cmdLine.rsIndexPrefetch;
403+
if (!prefetch.empty()) {
404+
IndexPrefetchConfig prefetchConfig = PREFETCH_ALL;
405+
if (prefetch == "none")
406+
prefetchConfig = PREFETCH_NONE;
407+
else if (prefetch == "_id_only")
408+
prefetchConfig = PREFETCH_ID_ONLY;
409+
else if (prefetch == "all")
410+
prefetchConfig = PREFETCH_ALL;
411+
else
412+
warning() << "unrecognized indexPrefetch setting: " << prefetch << endl;
413+
setIndexPrefetchConfig(prefetchConfig);
414+
}
400415
}
401416

402417
ReplSetImpl::ReplSetImpl() :

src/mongo/db/repl/rs.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,16 +515,32 @@ namespace mongo {
515515
threadpool::ThreadPool _prefetcherPool;
516516

517517
public:
518+
// Allow index prefetching to be turned on/off
519+
enum IndexPrefetchConfig {
520+
PREFETCH_NONE=0, PREFETCH_ID_ONLY=1, PREFETCH_ALL=2
521+
};
522+
523+
void setIndexPrefetchConfig(const IndexPrefetchConfig cfg) {
524+
_indexPrefetchConfig = cfg;
525+
}
526+
IndexPrefetchConfig getIndexPrefetchConfig() {
527+
return _indexPrefetchConfig;
528+
}
529+
518530
static const int replWriterThreadCount;
519531
static const int replPrefetcherThreadCount;
520532
threadpool::ThreadPool& getPrefetchPool() { return _prefetcherPool; }
521533
threadpool::ThreadPool& getWriterPool() { return _writerPool; }
522534

535+
523536
const ReplSetConfig::MemberCfg& myConfig() const { return _config; }
524537
bool tryToGoLiveAsASecondary(OpTime&); // readlocks
525538
void syncRollback(OplogReader& r);
526539
void syncThread();
527540
const OpTime lastOtherOpTime() const;
541+
542+
private:
543+
IndexPrefetchConfig _indexPrefetchConfig;
528544
};
529545

530546
class ReplSet : public ReplSetImpl {

src/mongo/s/commands_public.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ namespace mongo {
4545
return true;
4646
}
4747

48+
const char* fetchReplIndexPrefetchParam() {
49+
return "unsupported";
50+
}
51+
4852
namespace dbgrid_pub_cmds {
4953

5054
class PublicGridCommand : public Command {

0 commit comments

Comments
 (0)