Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/wix/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
mongodb-未使用日期索引_Mongodb - Fatal编程技术网

mongodb-未使用日期索引

mongodb-未使用日期索引,mongodb,Mongodb,集合事件具有userId和一个事件数组——数组中的每个元素都是一个嵌入式文档。例如: { "_id" : ObjectId("4f8f48cf5f0d23945a4068ca"), "events" : [ { "eventType" : "profile-updated", "eventId" : "247266", "eventDat

集合事件具有userId和一个事件数组——数组中的每个元素都是一个嵌入式文档。例如:

{
    "_id" : ObjectId("4f8f48cf5f0d23945a4068ca"),
    "events" : [
            {
                    "eventType" : "profile-updated",
                    "eventId" : "247266",
                    "eventDate" : ISODate("1938-04-27T23:05:51.451Z"),
            },
           {
                   "eventType" : "login",
                   "eventId" : "64531",
                   "eventDate" : ISODate("1948-05-15T23:11:37.413Z"),
           }
    ],
    "userId" : "junit-19568842",
}

使用如下查询查找过去30天内生成的事件:

db.events.find( { events : { $elemMatch: { "eventId" : 201, 
"eventDate" : {$gt : new Date(1231657163876) } } } }  ).explain()
查询计划显示,当测试数据包含较少的事件(大约20个)时,将使用“events.eventDate”上的索引:

}

但是,当有大量事件(大约500个)时,不使用索引:

{
    "cursor" : "BasicCursor",
    "nscanned" : 4,
    "nscannedObjects" : 4,
    "n" : 0,
    "millis" : 0,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "isMultiKey" : false,
    "indexOnly" : false,
    "indexBounds" : {

    }
}

当有很多事件时,为什么不使用索引?可能是什么时候
有大量的事件,MongoDB发现只扫描所有项目比使用索引更有效

MongoDB的查询优化器以一种特殊的方式工作。它只启动所有可用的计划,而不是计算特定查询计划的成本。无论哪一个先返回,都被认为是最优的,并将在将来使用

应用程序不断增长,数据不断增长和变化,最优计划可能在某些时候变得不最优。因此,mongo每隔一段时间重复一次查询选择过程

在这个具体案例中,基本扫描似乎是最有效的


链接:

使用$hint强制使用索引“events.eventDate”,nscannedObjects不包含索引

使用索引时的伪代码:

for(all entries in index matching the criteria) {
  get user object and scan to see if the eventId criteria is met
}
索引中与条件-->匹配的所有项每个事件都是索引中的一个项。因此,索引中的条目数将大于用户数。假设有4个用户对象和7个符合条件的事件,用户对象被扫描7次(for循环被执行7次)。未扫描索引时,所有4个用户对象仅检查一次。因此,使用索引时,扫描用户对象的次数比不使用索引时要多。这种理解正确吗

db.events.find( { events : { $elemMatch: { "eventId" : 201, 
"eventDate" : {$gt : new Date(1231657163876) } } } }  )
._addSpecial("$hint",{"events.eventDate":1}).explain()

{
    "cursor" : "BasicCursor",
    "nscanned" : 7,
    "nscannedObjects" : 7,
    "n" : 0,
    "millis" : 0,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "isMultiKey" : false,
    "indexOnly" : false,
    "indexBounds" : {

}

您正在抱怨优化器没有在需要0毫秒才能返回的查询上使用索引?:)上面的解释输出来自一个测试集合。对于大约2000万个文档,查询大约需要8秒钟。如果您要查询集合文档的很大一部分,像这样的范围查询可能会很慢。您可以使用提示来强制索引比较速度,但我认为它在执行索引扫描时同样慢。您应该根据生产数据发布解释,有提示也有提示。问题是,如果你发现了数百万个匹配的文档,那么检查它们需要一些时间。
db.events.find( { events : { $elemMatch: { "eventId" : 201, 
"eventDate" : {$gt : new Date(1231657163876) } } } }  )
._addSpecial("$hint",{"events.eventDate":1}).explain()

{
    "cursor" : "BasicCursor",
    "nscanned" : 7,
    "nscannedObjects" : 7,
    "n" : 0,
    "millis" : 0,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "isMultiKey" : false,
    "indexOnly" : false,
    "indexBounds" : {

}