ovi.ro

ovi.ro

MongoDB more indexes on Secondaries

I’ve been wondering for a time if it works, the documentation is not really clear if you can have different indexes on a replicaset secondary, maybe delayed or with priority 0.

Using this feature you can do reports better on a secondary (maybe delayed too) secondary server. Make sure the journal is big enough to allow secondary indexes to be built.

Step 1: Build replica set

a. Here are the replica set config files:

dbpath = /tmp/mongo/data
logpath = /tmp/mongo/log.log
replSet = rs0
port = 27100
fork = true
smallfiles = true
dbpath = /tmp/mongo/data1
logpath = /tmp/mongo/log1.log
replSet = rs0
port = 27101
fork = true
smallfiles = true
dbpath = /tmp/mongo/data2
logpath = /tmp/mongo/log2.log
replSet = rs0
port = 27102
fork = true
smallfiles = true

b. Start servers

> mongod --config mongodb-rpl-s0.conf
> mongod --config mongodb-rpl-s1.conf
> mongod --config mongodb-rpl-s2.conf

c. Configure replica set members

> mongo --port 27100
rs.add("127.0.0.1:27100")
rs.add("127.0.0.1:27101")
rs.add({_id:2, host:"127.0.0.1:27102",priority:0})

d. Add some data and indexes

use testdb
db.test.insert({a:1,b:1,c:1})
db.test.insert({a:2,b:2,c:2})
db.test.insert({a:3,b:3,c:3})
db.ensureIndex({a:1})

Step 2. Separate node and add indexes

a. Remove node from replicaset

rs.remove("127.0.0.1"27102")

b. Stop server

> mongo --port 27102
use admin
db.db.shutdownServer()

c. Modify config outside the replica set

dbpath = /tmp/mongo/data2
logpath = /tmp/mongo/log2.log
# replSet = rs0
port = 27102
fork = true
smallfiles = true

d. Start server

> mongod --config mongodb-rpl-s2.conf

e. Add index

use testdb
db.test.ensureIndex({c:1})

f. Meanwhile on the primary some inserts happen

db.test.insert({a:4,b:4,c:4})
db.test.insert({a:5,b:5,c:5})

Step 3. Rebuild replica set

a. Stop separated slave

mongo --port 27102
use admin
db.db.shutdownServer()

b. Modify back the config

dbpath = /tmp/mongo/data2
logpath = /tmp/mongo/log2.log
replSet = rs0
port = 27102
fork = true
smallfiles = true

c. Start server again

> mongod --config mongodb-rpl-s2.conf

d. Add back to replica set

> mongo --port 27100
rs.add({_id:2, host:"127.0.0.1:27102",priority:0})

e. Wait for synchronisation

> mongo --port 27102
use testdb
db.test.find() // documents with a:1 and a:2 will be synced

f. Test queries on primary

mongo --port 27100
db.test.find({a:1}).explain()
{
        "cursor" : "BtreeCursor a_1",
        "indexBounds" : {"a" : [[1,1]]},
        ...
}
db.test.find({c:1}).explain()    // NO INDEX ON c
{
        "cursor" : "BasicCursor",
         ...
}

g. Test queries on node 2

mongo --port 27102
db.test.find({a:1}).explain()
{
        "cursor" : "BtreeCursor a_1",
        "indexBounds" : {"a" : [[1,1]]},
        ...
}
db.test.find({c:1}).explain()    // HAVE AN INDEX ON c
{
        "cursor" : "BtreeCursor c_1",
        "indexBounds" : {"c" : [[1,1]]},
        ...
}

Didn’t have time for benchmarking, will do probably this in another post