• don't allow {_id:1} and {_id:2} • both match {x:null} • db.c.createIndex({x:1},{unique:true, dropDups:true}) • keeps first duplicate in natural order and drops the rest Tuesday, May 8, 12
any time • even when a collection already has data • creating an index will block MongoDB • unless you specify {background:true} • even background creation has an impact • recommend you create indexes at off peak times (using a script instead of ensureIndex) Tuesday, May 8, 12
using index {x:1} • db.c.find({x:{$in:[2,3]}}), using index {x:1} • db.c.find({"x.a":2}), using index {"x.a":1} • matches {_id:1,x:{a:2}} and {_id:2,x:{a:2,b:3}} • db.c.find({x:{a.2}}), using index {x:1} • matches {_id:1,x:{a:2}}, but not {_id:2,x:{a:2,b:3}} • What about: • db.c.find({$where:"this.x == 2"}) Tuesday, May 8, 12
index {x:1} • db.c.find({x:2}) • db.c.find({x:10}) • db.c.find({x:{$gt:5}}) • db.c.find({x:[2,10]}) • db.c.find({x:{$in:[2,5]}}) • What about: • db.c.find({x:{$all:[2,10]}}) • index will be used to lookup all x=2 Tuesday, May 8, 12
index {x:1,y:-1} • db.c.find({x:{$in:[2,3]}}), using index {x:1,y:1} • db.c.find().sort({x:1,y:1}), using index {x:1,y:1} • db.c.find().sort({x:-1,y:1}), using index {x:1:y-1} • db.c.find({x:2}).sort({y:1}), using index {x:1,y:1} Tuesday, May 8, 12
limit scan to numbers • db.c.find({x:{$not:/a/}}) • db.c.find({x:{$gte:0,$lte:10},y:5}), using index {x:1,y:1} • will scan from {x:0,y:5} to {x:10,y:5} • db.c.find({$where:"this.x == 5"}) Tuesday, May 8, 12
index {x:"2d"} • results are sorted from nearest to farthest • db.c.find({x:{$within:{$box:[[40,40], [60,60]]}}}), using index {x:"2d"} • db.c.find({x:{$within:{$center:[[50, 50], 10]}}}), using index {x:"2d"} • db.c.find({x:{$near:[50, 50]},y:2}), using index {x:"2d",y:1} Tuesday, May 8, 12
documents that have a value for the key • currently key must be a single field • can behave slightly differently • sort only returns documents in the index • {$exists:false} won't find any documents • you can combine sparse with unique to create a unique constraint that ignores missing values Tuesday, May 8, 12
index • Whether it is a covering index or not depends on the query and the fields returned • All the fields used in the query AND all the fields returned must be in the index • Often that means you must exclude _id from the results (unless _id is in the index) • Covering indexes are almost always compound indexes • Multikey indexes cannot be covering indexes • Use explain to verify that the index is covering with respect to a query ({indexOnly:true}) Tuesday, May 8, 12
watch out for logically equivalent indexes • {x:1} and {x:-1} • {x:1} and {x:1,unique:true} • indexes improve speed of queries but slow down inserts and updates • more specific indexes can be more helpful than less specific ones • {x:1,y:1} vs {x:1} Tuesday, May 8, 12
vs cost based • you can force an index to be used • db.c.find({x:2,y:3}).hint({y:1}) • uses {y:1} and ignores {x:1} • you can force a full collection scan • db.c.find({x:2}).hint({$natural:1}) • don't rely on order of results unless you use sort Tuesday, May 8, 12
• slow: > 100 ms (configurable) • records performance info in system.profile • query system.profile like any other collection • profiling impacts performance but not severely Tuesday, May 8, 12
unused indexes • redundant indexes • indexes with low selectivity • failure to consider compound indexes • poor understanding of how compound indexes work Tuesday, May 8, 12
slow down inserts and updates • Experiment: use explain and profiling • Be careful creating indexes on existing large collections • Be careful indexing array fields • Consider using compound indexes Tuesday, May 8, 12