When should I call ensureIndex
? Before inserting a single record, after inserting a single record, or before calling find()
?
7 Answers
It seems my comment has been a little misunderstood, so I'll clarify. It doesn't really matter when you call it so long as it's called at some point before you call find() for the first time. In other words, it doesn't really matter when you create the index, as long as it's there before you expect to use it.
A common pattern that I've seen a lot is coding the ensureIndex
at the same time (and in the same place) as the find()
call. ensureIndex
will check if the index exists and create it if it doesn't. There is undoubted some overhead (albeit very small) in calling ensureindex before ever call to find() so it's preferable not to do this.
I do call ensureIndex
in code to simplify deployments and to avoid having to manage the db and codebase separately. The tradeoff of ease of deployment balances out the redundancy of subsequent calls to ensureIndex (for me.)

- 23,217
- 7
- 60
- 77
-
what about the overhead? what does mongo do under the hood? I know it's B-Tree, when a new doc is added, where does it go in the tree? – Johnny Aug 09 '11 at 18:26
-
1EnsureIndex is basically testing for the existence of a specified index and creates it if it doesn't exist. There is minor overhead to do that check. Beyond that, every index carries overhead on writes, the goal is to choose your indexes carefully so that you're getting more benefit on the reads than you are incurring overhead on the writes. – Code Magician Aug 09 '11 at 18:30
-
3Given the throughput mongo can achieve doing twice the amount of commands, regardless of the efficiency of the ensureIndex early-out itself, is going to introduce significant bandwidth overhead. I'd certainly avoid doing it more than needed. – Remon van Vliet Aug 10 '11 at 11:50
-
Thank you for this post, it still holds true today. I was getting some bizarre errors where it appeared that mongo was swallowing my indexes. I saw your remark about calling it before anything else, and I think I got it all figured out now. – Seiyria Jun 28 '14 at 13:39
-
@CodeMagician please edit your answer. Calling `ensureIndex` before each find is completely wrong: index creation locks the whole database until the index is created, i.e. the first find could take seconds to minutes depending on collection size. A good approach might be to use `ensureIndex`/`createIndex` once at application start, **but still having in mind that it locks your database untile the creation process finishes**. – Alberto Dallaporta Aug 20 '18 at 08:55
-
`Deprecated since version 3.0.0: db.collection.ensureIndex() has been replaced by db.collection.createIndex().` source: https://docs.mongodb.com/manual/reference/method/db.collection.ensureIndex/ – Zap Dec 18 '20 at 10:24
I'd recommend calling ensureIndex once, when your application starts.

- 31,444
- 34
- 152
- 221
-
1source: http://docs.mongodb.org/manual/faq/indexes/#should-you-run-ensureindex-after-every-insert – Daniel Magnusson Dec 12 '14 at 13:42
-
That's not my 'source' but yes it's saying the same thing effectively. – UpTheCreek Dec 12 '14 at 13:45
-
would like to clarify. I don't need to use ensureIndex for the id's that provided by default ? – Shulz Sep 30 '21 at 02:21
It doesn't matter, but you only have to do this once. If you want to batch insert a large amount of data to an empty collection then it is best to create the index after the inserts but otherwise it doesn't really matter.

- 94,607
- 11
- 117
- 176
You only need to do this once. Example:
db.table.insert({foo: 'bar'});
var foo = db.table.findOne({foo: 'bar'}); // => delivered from FS, not RAM
db.table.ensureIndex({foo: 1});
var foo = db.table.findOne({foo: 'bar'}); // => delivered from RAM, not FS
db.table.insert({foo: 'foo'});
var foo = db.table.findOne({foo: 'foo'}); // => delivered from RAM, not FS

- 10,127
- 4
- 40
- 57
-
4all of them are going to be delivered from the RAM. indexing != RAM. – Karoly Horvath Aug 09 '11 at 18:18
-
http://www.mongodb.org/display/DOCS/Indexing+Advice+and+FAQ#IndexingAdviceandFAQ-MakesureyourindexescanfitinRAM. – cutsoy Aug 09 '11 at 18:24
-
-
@TimvanElsloo - I believe it's worthwhile to note that the OS can take RAM away from Mongo. As a result, is it referentially transparent that, for every 2nd and 3rd find(), you'll always hit RAM? at Karoly, could you please explain your first comment? – Kevin Meredith Oct 22 '13 at 19:25
I typically put my ensureIndex()
calls within an init block for the part of my application that manages communication with MongoDB. Also, I wrap those ensureIndex()
calls within a check for existence of a collection I know must exist for the application to function; this way, the ensureIndex() calls are only ever called once, ever, the first time the application is run against a specific MongoDB instance.
I've read elsewhere an opinion against putting ensureIndex() calls in application code, as other developers can mistakenly change them and alter the DB (the indexes), but wrapping it in a check for a collection's existence helps to guard against this.
Java MongoDB driver example:
DB db = mongo.getDB("databaseName");
Set<String> existingCollectionNames = db.getCollectionNames();
// init collections; ensureIndexes only if creating collection
// (let application set up the db if it's not already)
DBCollection coll = db.getCollection("collectionName");
if (!existingCollectionNames.contains("collectionName")) {
// ensure indexes...
coll.ensureIndex(BasicDBObjectBuilder.start().add("date", 1).get());
// ...
}

- 24,913
- 29
- 97
- 127
If you have a collection that have millions of records and you are building multiple compound indices with auto-indexing turned off then you MUST ensure that you are invoking ensureIndexes() much before your first find query, possibly synchronously i.e. after ensureIndexes method returns.
The mode(foreground vs background) in which indexes are build adds extra complexity. Foreground mode locks the complete db while it is building the indexes whereas background mode allows you to query the db. However background mode of index building takes extra time.
So you must make sure that indexes have been created successfully. You can use db.currentOp() to check progress of ensureIndexes() while it is still creating indexes.

- 1,027
- 9
- 8
If you add an index before hand, every insert/update/delete call has to modify each index also. So, from an optimization stand point, you probably want to put it off as long as possible before issuing queries. However, from a functional stand point, it doesn't matter.

- 2,102
- 2
- 14
- 20