Compound Index Vs Multiple Single Field Index in MongoDB 3.x
MongoDB supports both compound index and single field index. It's a common knowledge that index decrease your INSERTS/UPDATES performance but increases your SELECT performance. However, if you need to index multiple fields, is it better to use a compound index or just create multiple single field indexes? This post tries to investigate which is the better option in terms of performance.
Insert Performance
Test Setup:
- Single MongoDB 3.2 instance running on my Mac
- POC Driver uses single thread to perform inserts only
- Test run for 5 mins
- Empty collection after every run
- Default readConcern
- Default writeConcern
Sample Document:
> db.testCol.findOne() { "_id" : { "w" : 2, "i" : 0 }, "fld0" : NumberLong(530752), "fld1" : ISODate("2015-06-02T08:14:18.687Z"), "fld2" : "tempor invidunt ut labore et", "fld3" : "eirmod tempor invidunt ut", "fld4" : "Lorem ipsum dolor sit amet,", "fld5" : ISODate("2016-10-12T01:58:24.580Z"), "fld6" : NumberLong(1712708), "fld7" : "sit amet. Lorem ipsum dolor", "fld8" : "sit amet, consetetur", "fld9" : NumberLong(652363), "bin" : BinData(0,"") }
Phase 1 (No indexes except on _id field)
After 295 seconds, 13340672 new records inserted - collection has 13340672 in total 46498 inserts per second since last report 99.97 % in under 50 milliseconds 0 keyqueries per second since last report 100.00 % in under 50 milliseconds 0 updates per second since last report 100.00 % in under 50 milliseconds 0 rangequeries per second since last report 100.00 % in under 50 milliseconds
~45,222 inserts/second
Phase 2 (Compound index on fld1 to fld9)
After 295 seconds, 7739904 new records inserted - collection has 7739904 in total 20830 inserts per second since last report 99.72 % in under 50 milliseconds 0 keyqueries per second since last report 100.00 % in under 50 milliseconds 0 updates per second since last report 100.00 % in under 50 milliseconds 0 rangequeries per second since last report 100.00 % in under 50 milliseconds
~26,236 inserts/second
Phase 3 (Single field indexes on each fld2, fld6 and fld8)
After 295 seconds, 2998272 new records inserted - collection has 2998272 in total 7012 inserts per second since last report 63.61 % in under 50 milliseconds 0 keyqueries per second since last report 100.00 % in under 50 milliseconds 0 updates per second since last report 100.00 % in under 50 milliseconds 0 rangequeries per second since last report 100.00 % in under 50 milliseconds
~10,163 inserts/second
Storage Utilisation
On the same collection with 2,817,024 documents:
Compound Index
db.testCol.stats().indexSizes { "_id_" : 75079680, "fld0_1_fld1_1_fld2_1_fld3_1_fld4_1_fld5_1_fld6_1_fl7_1_fld8_1_fld9_1" : 2617061376 }
~2.44GB
Single-Field Index
> db.testCol.stats().indexSizes { "_id_" : 75079680, "fld0_1" : 65343488, "fld1_1" : 79781888, "fld2_1" : 35471360, "fld3_1" : 35475456, "fld4_1" : 35475456, "fld5_1" : 79781888, "fld6_1" : 65339392, "fld7_1" : 35475456, "fld8_1" : 35475456, "fld9_1" : 65347584, }
~0.53GB
Index Selectivity Usage
For single-field index, there's no limitation at all. MongDB optimiser will pick and choose whichever index it deems fit. For compound index, it's slightly different.
Query like these will not use the compound index:
- db.testCol.find({fld9:1,fld8:1,fld7:1})
- db.testCol.find({fld9:1,fld3:1,fld6:1})
- db.testCol.find({fld9:1,fld8:1,fld7:1})
Query like these will use the compound index:
- db.testCol.find({fld0:1,fld1:1})
- db.testCol.find({fld5:1,fld8:1,fld0:1}) (not very efficient..)
- db.testCol.find({fld0:1,fld3:1,fld5:1})
The general idea is that MongoDB will use it the compound index if it matches the index prefix. It it doesn't match it correctly, it might still use the index if it is still more efficient that performing a full collection scan. The only way to find out is educate and test the queries yourself!
Summary
A very short summary in key points below:
- No index has the best insert performance (duh!!)
- Compound index is faster than Single-field index in insert performance
- Compound index uses more storage than Single-field index
Depending on the situation, choose your poison carefully :)
References:
- https://github.com/johnlpage/POCDriver
- https://docs.mongodb.com/v3.2/core/index-compound/
- https://docs.mongodb.com/v3.2/core/index-single/
- https://docs.mongodb.com/manual/indexes/
- https://www.mongodb.com/collateral/mongodb-performance-best-practices
P.S: The above test does not attempt to quantify the absolute performance numbers but rather provide a good performance degradation ratio for indexes
Regards,
Wei Shan
Top comments (0)