Моя структура документа выглядит следующим образом
{
"_id" : "311acd33a0ae8dcc3101246f90af9dc5",
"created_datetime" : ISODate("2013-04-05T10:35:31.143Z"),
"installs" : [
{
"status" : 1,
"app" : "xyz",
"reg_id" : "AVJyaIFI2Q8v93YmOHI5kEOVoCLbd4CAUyVK9zLrC1QCiBcl_bw89i5PvhEuTKmxtb4x130vjMyo78zPI7cedErcRv_Jjn0BN3Wq40hhg",
"last_action_datetime" : ISODate("2013-04-05T10:35:31.143Z"),
"version" : "2"
},
{
"status" : 1,
"app" : "abc",
"reg_id" : "AVJyaIFI2Q8v93YmOHI5kEOVoCLbd4CAUyVK9zLrC1QCiBcl_bw89i5PvhEuTKmxtb4x130vjMyo78zPI7cedErcRv_Jjn0BN3Wq40hhg",
"last_action_datetime" : ISODate("2013-04-05T10:35:31.143Z"),
"version" : "5"
},
{
"status" : 1,
"app" : "pqr",
"last_action_datetime" : ISODate("2013-04-06T10:35:31.143Z"),
"version" : "1"
},
],
"last_update" : ISODate("2013-04-12T06:26:46.333Z"),
"num_updates" : 9,
.....
}
и у меня есть составной индекс на 'install.reg_id'
и 'installs.status'
и один индекс 'installs.status'
Теперь я хочу найти все документы, где, по меньшей мере, на элемент installs
содержит reg_id
, а также его status
равен 1. Таким образом, я запрос
db.users.find({'installs': {'$elemMatch': {'reg_id': {'$exists': true}, 'status': 1}}}).explain()
я получить
{
"cursor" : "BtreeCursor installs.status_1",
"isMultiKey" : true,
"n" : 1447034,
"nscannedObjects" : 1720864,
"nscanned" : 1720864,
"nscannedObjectsAllPlans" : 1720864,
"nscannedAllPlans" : 1720864,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 13072,
"nChunkSkips" : 0,
"millis" : 11063,
"indexBounds" : {
"installs.status" : [
[
1,
1
]
]
},
"server" : "####:27017"
}
Так вот составной индекс должен был использоваться, но не используется. Я думал, что $elemMatch
является виновником, так что я сделал этот запрос,
db.users.find({'installs.reg_id': {'$exists': true}}).explain()
и я получаю
{
"cursor" : "BasicCursor",
"isMultiKey" : false,
"n" : 2947446,
"nscannedObjects" : 3184871,
"nscanned" : 3184871,
"nscannedObjectsAllPlans" : 3184871,
"nscannedAllPlans" : 3184871,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 23865,
"nChunkSkips" : 0,
"millis" : 16172,
"indexBounds" : {
},
"server" : "####:27017"
}
Это показывает, что запрос не использует какие-либо индексов.
Подумайте, что здесь не так?
Обновления: Добавление подсказки делает использование запроса индексы
db.users.find({'installs': {'$elemMatch': {'reg_id': {'$exists': true}, 'status': 1}}}).hint({"installs.reg_id":1,"installs.status":1}).explain()
возвращает
{
"cursor" : "BtreeCursor installs.reg_id_1_installs.status_1",
"isMultiKey" : true,
"n" : 1451589,
"nscannedObjects" : 2464985,
"nscanned" : 4373261,
"nscannedObjectsAllPlans" : 2464985,
"nscannedAllPlans" : 4373261,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 20170,
"nChunkSkips" : 0,
"millis" : 106353,
"indexBounds" : {
"installs.reg_id" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
],
"installs.status" : [
[
1,
1
]
]
},
"server" : "####:27017"
}
Здесь используется индекс соединения.
вы можете включить еще одну объяснить - с намеком? Поэтому повторите запрос elemMatch, но после запроса, прежде чем объяснять() добавить .hint ({"installs.reg_id": 1, "installs.status": 1}) –
@ АсяКамский Я обновил свой вопрос. спасибо, но все еще существует большая разница между 'n' и' nscanned'. Почему это, если индекс используется? – lovesh
это из-за избирательности индекса (или его отсутствия). Я сочиняю полный ответ. –