Behavior of createIndex for an existing index

Hi,
What is the mongo behavior when a createIndex command is reissued for an existing index on an existing collection?
We use spring-mongo to interact with the db and are using @indexed for index creation in application. This means that the createIndex command is reissued every time the application starts up. Is there a performance overhead from this? I would expect this to get ignored by mongo but would love to get a clarification since i couldnt find anything concrete in the documentation.
Appreciate any leads. Thanks!

From mongo documentation

https://docs.mongodb.com/manual/reference/method/db.collection.createIndex/

If you call db.collection.createIndex() for an index that already exists, MongoDB does not recreate the index.

Is this applicable for older mongo versions? We use 3.6 and 4.0

Hi @Sneh_Bharati,

Behaviour for attempted re-creation of an existing index is the same in older versions of MongoDB. Create index commands will not recreate existing indexes and instead return a success message indicating “all indexes already exist” (the underlying server createIndexes command supports creating one or more indexes).

However, since you are using MongoDB 3.6 and 4.0 there is an important caveat if your application is ensuring indexes on startup. The default behaviour is to build new indexes in the foreground, which can have significant consequences for a production environment.

Foreground index builds on a populated collection in MongoDB 4.0 and older will block all other operations on the database that holds the collection, so you would not want to accidentally have lengthy index builds start unless you also have a planned maintenance window.

To avoid this issue you can either set the background property to true in your Spring index annotation using @Indexed(background=true), or use an admin strategy like rolling index builds for a replica set or sharded cluster. See: Index Build Operations on a Populated Collection (MongoDB 4.0).

MongoDB 4.2+ uses an optimised index build process to minimise the impact on a production deployment. Collection-level locks are briefly held at the beginning and end of the process, but the rest of the index build runs as a background task. See: Index Builds on Populated Collections (MongoDB 4.2).

Unfortunately Spring Data does not currently provide a way to set a global default for background indexes. A relevant issue to upvote and watch is DATAMONGO-1895: Add option to specify default background index building in AbstractMongoConfiguration in Spring Data’s issue tracker.

Regards,
Stennie

1 Like

I think yes
You can try it out on some test DB/collection

I tested it on 4.0.5

First run created new index
“createdCollectionAutomatically” : false,
“numIndexesBefore” : 1,
“numIndexesAfter” : 2,
“ok” : 1

Second run when i try to create index on same field

“numIndexesBefore” : 2,
“numIndexesAfter” : 2,
“note” : “all indexes already exist”,
“ok” : 1

Spring data does allow passing an optional parameter to specify indexing in background vs foreground. I havent tried it out yet - but thats what we are planning to do going forward.
Thanks for your help.

Hi @Sneh_Bharati,

Yes, that is the option I mentioned: @Indexed(background=true).

However, you also have to include that for every index annotation rather than configuring a global default (as suggested in DATAMONGO-1895).

Regards,
Stennie

1 Like