Mongodb 扫描整个索引,非常慢,使用 WiredTiger

Mongodb whole index scanned, very slow, using WiredTiger

我有一个设置了以下索引的设备集合:

{
  "v" : 1,
  "key" :
  { "sdk.id" : 1, 
    "sdk.createdAt" : 1, 
    "sdk.updatedAt" : 1, 
    "deviceInfo.isTablet" : 1 },
  "name" : "sdk.id_1_sdk.createdAt_1_sdk.updatedAt_1_deviceInfo.isTablet_1",
  "ns" : "company.Device"
}

我的文档是这样的:

{
   _id: ObjectId("something"),
   property: 'abcd',
   sdk: [
      { id: 'ab', createdAt: new Date(), updatedAt: new Date()},
      { id: 'ac', createdAt: new Date(), updatedAt: new Date()},
   ]
}

当我这样做时 db.Device.explain(1).find({'sdk.id': 'ab'}).count() 我得到:

{
    "queryPlanner" : {
        "plannerVersion" : 1,
        "namespace" : "company.Device",
        "indexFilterSet" : false,
        "parsedQuery" : {
            "sdk.id" : {
                "$eq" : "ab"
            }
        },
        "winningPlan" : {
            "stage" : "COUNT",
            "inputStage" : {
                "stage" : "COUNT_SCAN",
                "keyPattern" : {
                    "sdk.id" : 1,
                    "sdk.createdAt" : 1,
                    "sdk.updatedAt" : 1,
                    "deviceInfo.isTablet" : 1
                },
                "indexName" : "sdk.id_1_sdk.createdAt_1_sdk.updatedAt_1_deviceInfo.isTablet_1",
                "isMultiKey" : true
            }
        },
        "rejectedPlans" : [ ]
    },
    "executionStats" : {
        "executionSuccess" : true,
        "nReturned" : 0,
        "executionTimeMillis" : 712,
        "totalKeysExamined" : 569865,
        "totalDocsExamined" : 0,
        "executionStages" : {
            "stage" : "COUNT",
            "nReturned" : 0,
            "executionTimeMillisEstimate" : 636,
            "works" : 569865,
            "advanced" : 0,
            "needTime" : 569864,
            "needFetch" : 0,
            "saveState" : 4452,
            "restoreState" : 4452,
            "isEOF" : 1,
            "invalidates" : 0,
            "nCounted" : 569863,
            "nSkipped" : 0,
            "inputStage" : {
                "stage" : "COUNT_SCAN",
                "nReturned" : 569863,
                "executionTimeMillisEstimate" : 616,
                "works" : 569864,
                "advanced" : 569863,
                "needTime" : 1,
                "needFetch" : 0,
                "saveState" : 4452,
                "restoreState" : 4452,
                "isEOF" : 1,
                "invalidates" : 0,
                "keysExamined" : 569865,
                "keyPattern" : {
                    "sdk.id" : 1,
                    "sdk.createdAt" : 1,
                    "sdk.updatedAt" : 1,
                    "deviceInfo.isTablet" : 1
                },
                "indexName" : "sdk.id_1_sdk.createdAt_1_sdk.updatedAt_1_deviceInfo.isTablet_1",
                "isMultiKey" : true
            }
        },
        "allPlansExecution" : [ ]
    },
    "serverInfo" : {
        "host" : "rs-primary",
        "port" : 27000,
        "version" : "3.0.2",
        "gitVersion" : "6201872043ecbbc0a4cc169b5482dcf385fc464f"
    },
    "ok" : 1
}

如您所见,请求非常非常慢,并且仅在我们切换到 WiredTiger 之后才出现(之前是紧接的)。

该集合包含 ~600k 文档,并且有 ~550k 文档 sdk.id $eq ab.

有人可以解释一下上面的解释吗?我找不到任何关于 isEOF、saveState 和 restoreState

的信息

谢谢

isEOF:指定执行阶段是否已经到达流的末尾

saveState 和 restoreState :在 Mongo 3.0 中,这些是查询阶段产生 (saveState) 然后恢复 (restoreState) 的次数的计数器。例如,集合扫描 (COLLSCAN) 阶段可能需要屈服以获取尚未在内存中的文档。查询也会产生,因此它们可以与其他查询交错并通过 $maxTimeMS 或 kill 操作安全停止。

这些数字本身并不是很有趣。如果您 运行 多次连续解释同一个查询,您会注意到数字会根据当时的其他操作以及当时是否所有必需的文档都在内存中而变化。