how to structure a compound index in mongodb

前端 未结 1 1742
旧时难觅i
旧时难觅i 2020-12-09 14:46

I need some advice in creating and ordering indexes in mongo.

I have a post collection with 5 properties:

Posts

  • status
  • start date
相关标签:
1条回答
  • 2020-12-09 15:06

    That's a lot of questions in one post ;) Let me go through them in a practical order :

    • Every query can use at most one index (with the exception of top level $or clauses and such). This includes any sorting.
    • Because of the above you will definitely need a compound index for your problem rather than seperate per-field indexes.
    • Low cardinality fields (so, fields with very few unique values across your dataset) should usually not be in the index since their selectivity is very limited.
    • Order of the fields in your compound index matter, and so does the relative direction of each field in your compound index (e.g. "{name:1, age:-1}"). There's a lot of documentation about compound indexes and index field directions on mongodb.org so I won't repeat all of it here.
    • Sorts will only use the index if the sort field is in the index and is the field in the index directly after the last field that was used to select the resultset. In most cases this would be the last field of the index.

    So, you should not include status in your index at all since once the index walk has eliminated the vast majority of documents based on higher cardinality fields it will at most have 2-3 documents left in most cases which is hardly optimized by a status index (especially since you mentioned those 2-3 documents are very likely to have the same status anyway).

    Now, the last note that's relevant in your case is that when you use range queries (and you are) it'll not use the index for sorting anyway. You can check this by looking at the "scanAndOrder" value of your explain() once you test your query. If that value exists and is true it means it'll sort the resultset in memory (scan and order) rather than use the index directly. This cannot be avoided in your specific case.

    So, your index should therefore be :

    db.posts.ensureIndex({start:1, end:1})
    

    and your query (order modified for clarity only, query optimizer will run your original query through the same execution path but I prefer putting indexed fields first and in order) :

    db.posts.find({start: {$lt: today}, end: {$gt: today}, status: {$gte:0}}).sort({sortOrder:1})
    
    0 讨论(0)
提交回复
热议问题