好了,所以添加索引後的解釋看起來是正確的,確實使用索引:
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "users",
"indexFilterSet" : false,
"parsedQuery" : {
"role" : {
"$eq" : "seeker"
}
},
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"role" : 1
},
"indexName" : "role_1",
"isMultiKey" : false,
"direction" : "forward",
"indexBounds" : {
"role" : [
"[\"seeker\", \"seeker\"]"
]
}
}
},
"rejectedPlans" : [ ]
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 850834,
"executionTimeMillis" : 13217,
"totalKeysExamined" : 850834,
"totalDocsExamined" : 850834,
"executionStages" : {
"stage" : "FETCH",
"nReturned" : 850834,
"executionTimeMillisEstimate" : 1970,
"works" : 941141,
"advanced" : 850834,
"needTime" : 0,
"needFetch" : 90306,
"saveState" : 93946,
"restoreState" : 93946,
"isEOF" : 1,
"invalidates" : 0,
"docsExamined" : 850834,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 850834,
"executionTimeMillisEstimate" : 560,
"works" : 850834,
"advanced" : 850834,
"needTime" : 0,
"needFetch" : 0,
"saveState" : 93946,
"restoreState" : 93946,
"isEOF" : 1,
"invalidates" : 0,
"keyPattern" : {
"role" : 1
},
"indexName" : "role_1",
"isMultiKey" : false,
"direction" : "forward",
"indexBounds" : {
"role" : [
"[\"seeker\", \"seeker\"]"
]
},
"keysExamined" : 850834,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0,
"matchTested" : 0
}
}
},
"serverInfo" : {
"host" : "xxx",
"port" : 12345,
"version" : "3.0.12",
"gitVersion" : "33934938e0e95d534cebbaff656cde916b9c3573"
},
"ok" : 1
}
我認爲這是你可以通過做得到最快的事「檢索一次全部」。 我不知道你是否能retrieve only specific fields,像「名」,只有「電子郵件」:
如果不指定推算,find()方法返回的 各個領域與查詢匹配的所有文件。
db.inventory.find({type:'food'})此操作將返回庫存集合中所有類型爲 字段值爲'food'的 文檔。返回的文件包含所有字段。
所以,如果你不想蒙戈返回的所有字段爲每一位學生,只是通過一些額外的參數,如:
db.users.find({ role: 'student' }, { name: 1, email: 1, _id:0 })
顯然讀取所有領域,從你的硬盤一個耗時的操作,因此,從10只獲取2場會給您的查詢顯著提升。在SQL方面,它是之間的差異:select * from T
和select name from T
。
我不知道你有沒有考慮使用分頁和配料接收/發送,即檢索學生的第一個10000,送他們發送電子郵件,然後檢索下一個10000級的學生,向他們發送電子郵件,重複..?
你也可以嘗試通過將你的mongo db實例中的用戶分割來進行橫向擴展,但這取決於你的硬件功能,我不認爲如果你只有一臺服務器,它會給你帶來任何好處。所以,分頁應該是一條路。
從集合中獲取百萬個文檔是很多文檔,即使索引正確。你看過流式傳輸的結果,如[這裏](http://stackoverflow.com/a/21630141/1259510)所示? – JohnnyHK
流媒體很有趣。我認爲這個使用案例存在超過10,000家公司toda,他們是怎麼做到的。例如讓我們說,LinkedIn必須在下午5點向所有人發送工作提醒郵件。 LinkedIn會從數據庫中提取多少封電子郵件,然後遍歷電子郵件數組中的每封電子郵件,找到匹配的作業+準備好的電子郵件模板,然後將該電子郵件發送給全世界100多個用戶100萬次 – PureText