1. 程式人生 > >MongoDB實戰-使用EXPLAIN分析慢查詢

MongoDB實戰-使用EXPLAIN分析慢查詢

    除了MongoDB的剖析器,可以很方便地找到慢查詢。但是要知道這些查詢為什麼慢會更麻煩一些,因為這個過程中可能還要求有點“偵查工作”。正如前面所說,慢查詢的原因是多種多樣的。走運的話,加個索引就能解決慢查詢。在更復雜的情況下,可能不得不重新安排索引、重建資料模型、或者升級硬體。

     最簡單的情況裡,問題的根本原因是缺少索引,索引不當或者查詢不理想。通過剖析器定位了慢查詢後,可以在慢查詢上使用explain()來確認原因。explain的使用方式是在執行語句後面加上explain。3.x版本後的explain用法,explain(true)代表allPlansExecution mode,傳入false代表queryPlanner mode.使用.explain(true).modeName可以顯示具體的操作模式。

db.stock.find({}).sort({close:-1}).limit(1).explain(true)
執行結果如下:

executionTimeMillis指出了執行時間超過28s。其原因明顯,totalDocsExamined的值,它表明查詢引擎必須掃描4308303個文件才能完成查詢。這個正是這個集合的總文件數。表明該查詢需要全集合掃描。如果你希望查詢返回集合裡的全部文件,這倒不是一件壞事。但是如果你僅僅希望返回一個文件,正如explain中的nReturned所示,這就成問題了。

     一般來說我們希望nRetrurned和totalDocsExamined的值儘可能接近。在進行集合掃描時,情況往往不是這樣的。winningPlan中沒有出現index說明你掃描的是集合本身而非索引。對於這種應用場景,我們只需要在colse欄位上增加一個索引。

db.stock.ensureIndex({close:1})
db.stock.find({}).sort({close:-1}).limit(1).explain(true).executionStats

再次執行查詢explain語句


差距出現了,執行時間都不到1ms。再次執行

db.stock.find({}).sort({close:-1}).limit(1).explain(true).queryPlanner

通過查詢模式的顯示,發現使用了close_1的索引。且stage為IXSCAN。在indexBounds屬性裡,可以看到MaxKey和MinKey兩個特殊值,說明查詢橫跨了整個索引。此時查詢優化器經過最右邊才找到最大值,然後沿原路返回。因為限制了結果集為1,在找到最大元素後查詢就完成了。下面我們在檢視下收盤價大於500的查詢語句的expliain輸出。

db.stock.find({close:{$gt:500}}).explain(true).queryPlanner

執行
db.stock.find({close:{$gt:500}}).explain(true).executionStats

比較發現,掃描文件數和返回文件數的數值是相同。這是理想情況。注意此時 索引邊界的下邊界是500,上邊界是無限大。這些值必須和正在查詢的值使用相同的資料型別。在查詢的為數字,索引邊界就是數字;在查詢的是字串,索引邊界就是字串。