再MongoDB中可以使用db.collection.explain("executionStats")語句對查詢效能進行分析。
在MongoDB中建立表inventory並插入測試資料,初始資料除了ID欄位以為是不帶任何索引的。
{ "_id" : 1, "item" : "f1", type: "food", quantity: 500 }{ "_id" : 2, "item" : "f2", type: "food", quantity: 100 }{ "_id" : 3, "item" : "p1", type: "paper", quantity: 200 }{ "_id" : 4, "item" : "p2", type: "paper", quantity: 150 }{ "_id" : 5, "item" : "f3", type: "food", quantity: 300 }{ "_id" : 6, "item" : "t1", type: "toys", quantity: 500 }{ "_id" : 7, "item" : "a1", type: "apparel", quantity: 250 }{ "_id" : 8, "item" : "a2", type: "apparel", quantity: 400 }{ "_id" : 9, "item" : "t2", type: "toys", quantity: 50 }{ "_id" : 10, "item" : "f4", type: "food", quantity: 75 }
我們在不使用索引的情況下進行條件查詢,下面的檢索條件是 quantity>=100 and quantity<= 200。
db.inventory.find( { quantity: { $gte: 100, $lte: 200 } } )
查詢會返回3條記錄。
{ "_id" : 2, "item" : "f2", "type" : "food", "quantity" : 100 }{ "_id" : 3, "item" : "p1", "type" : "paper", "quantity" : 200 }{ "_id" : 4, "item" : "p2", "type" : "paper", "quantity" : 150 }
然後我們查看查詢計劃。
db.inventory.find( { quantity: { $gte: 100, $lte: 200 } }).explain("executionStats")
返回以下結果:
{ "queryPlanner" : { "plannerVersion" : 1, ... "winningPlan" : { "stage" : "COLLSCAN", ... } }, "executionStats" : { "executionSuccess" : true, "nReturned" : 3, "executionTimeMillis" : 0, "totalKeysExamined" : 0, "totalDocsExamined" : 10, "executionStages" : { "stage" : "COLLSCAN", ... }, ... }, ...}
queryPlanner.winningPlan.stage:"COLLSCAN" 說明進行了全表掃描
executionStats.nReturned:3 說明查詢匹配到3條記錄
executionStats.totalDocsExamined:10 說明MongoDB掃描了10次記錄,我們的測試資料一共10條,也就是說進行了全表掃描,如果測試資料有1000條,那麼這裡就會掃描1000次
總結:不使用索引,查詢到3條匹配的記錄需要進行全表掃描,如果資料量很大會導致效能低下,後果很嚴重。
使用索引查詢,先建立索引
db.inventory.createIndex( { quantity: 1 } )
查看查詢計劃
db.inventory.find( { quantity: { $gte: 100, $lte: 200 } }).explain("executionStats")
返回以下結果
{ "queryPlanner" : { "plannerVersion" : 1, ... "winningPlan" : { "stage" : "FETCH", "inputStage" : { "stage" : "IXSCAN", "keyPattern" : { "quantity" : 1 }, ... } }, "rejectedPlans" : [ ] }, "executionStats" : { "executionSuccess" : true, "nReturned" : 3, "executionTimeMillis" : 0, "totalKeysExamined" : 3, "totalDocsExamined" : 3, "executionStages" : { ... }, ... }, ...}
queryPlanner.winningPlan.inputStage.stage:'IXSCAN' 說明使用了索引
executionStats.nReturned:3 說明查詢匹配到3條記錄
executionStats.totalKeysExamined:3 說明MongoDB查詢了3次索引
executionStats.totalDocsExamined:3 說明MongoDB掃描了3次記錄,利用索引後直接定位“文檔”的位置,所以3次掃描即可完成查詢。
總結:使用索引後,查詢到3條匹配的記錄 需要掃描3次索引,即可完成查詢,效能顯著提升。