2012-10-23 28 views
7

我堅持這個簡單的前綴查詢。雖然Mongo docs狀態,你可以通過使用前綴正則表達式格式得到相當不錯的性能(/^A /),查詢是相當緩慢的,當我嘗試對結果進行排序:Mongodb簡單的前綴查詢與正則表達式和排序很慢

940米利斯

db.posts.find({#標籤:/ ^新聞短片/})。極限(15)的.sort({等級:-1})。。暗示( 'hashtags_1_rank_-1')解釋()

{ 
"cursor" : "BtreeCursor hashtags_1_rank_-1 multi", 
"isMultiKey" : true, 
"n" : 15, 
"nscannedObjects" : 142691, 
"nscanned" : 142692, 
"nscannedObjectsAllPlans" : 142691, 
"nscannedAllPlans" : 142692, 
"scanAndOrder" : true, 
"indexOnly" : false, 
"nYields" : 1, 
"nChunkSkips" : 0, 
"millis" : 934, 
"indexBounds" : { 
    "hashtags" : [ 
     [ 
      "noticias", 
      "noticiat" 
     ], 
     [ 
      /^noticias/, 
      /^noticias/ 
     ] 
    ], 
    "rank" : [ 
     [ 
      { 
       "$maxElement" : 1 
      }, 
      { 
       "$minElement" : 1 
      } 
     ] 
    ] 
}, 
"server" : "XRTZ048.local:27017" 
} 

但是,相同查詢的未排序版本超快速:

0米利斯

db.posts.find。({#標籤:/ ^新聞短片/})極限(15).hint( 'hashtags_1_rank_-1')解釋()

{ 
"cursor" : "BtreeCursor hashtags_1_rank_-1 multi", 
"isMultiKey" : true, 
"n" : 15, 
"nscannedObjects" : 15, 
"nscanned" : 15, 
"nscannedObjectsAllPlans" : 15, 
"nscannedAllPlans" : 15, 
"scanAndOrder" : false, 
"indexOnly" : false, 
"nYields" : 0, 
"nChunkSkips" : 0, 
"millis" : 0, 
"indexBounds" : { 
    "hashtags" : [ 
     [ 
      "noticias", 
      "noticiat" 
     ], 
     [ 
      /^noticias/, 
      /^noticias/ 
     ] 
    ], 
    "rank" : [ 
     [ 
      { 
       "$maxElement" : 1 
      }, 
      { 
       "$minElement" : 1 
      } 
     ] 
    ] 
}, 
"server" : "XRTZ048.local:27017" 

}

查詢也快,如果我刪除了正則表達式和排序:

0米利斯

db.posts.find({#標籤: '新聞短片'})極限(15)的.sort({等級:-1})。。暗示( 'hashtags_1_rank_-1')。解釋()

{ 
"cursor" : "BtreeCursor hashtags_1_rank_-1", 
"isMultiKey" : true, 
"n" : 15, 
"nscannedObjects" : 15, 
"nscanned" : 15, 
"nscannedObjectsAllPlans" : 15, 
"nscannedAllPlans" : 15, 
"scanAndOrder" : false, 
"indexOnly" : false, 
"nYields" : 0, 
"nChunkSkips" : 0, 
"millis" : 0, 
"indexBounds" : { 
    "hashtags" : [ 
     [ 
      "noticias", 
      "noticias" 
     ] 
    ], 
    "rank" : [ 
     [ 
      { 
       "$maxElement" : 1 
      }, 
      { 
       "$minElement" : 1 
      } 
     ] 
    ] 
}, 
"server" : "XRTZ048.local:27017" 

}

好像同時使用正則表達式和排序使得蒙戈掃描大量的記錄。但是,如果我不使用正則表達式,排序只掃描15。這裏有什麼問題?

+1

jaime,我認爲''scanAndOrder''負責緩慢。你可能想看看[安德烈的答案](http://stackoverflow.com/questions/11871187/removing-scanandorder-true-in-my-mongodb-query-result),這可能是相似的,如果不是完全一樣的問題。 – slee

回答

6

解釋輸出中的scanAndOrder: true指示查詢不得不檢索文檔,然後在返回輸出之前將它們排序在內存中。這是一項昂貴的操作,並且會影響查詢的性能。

012解釋輸出中scanAndOrder: true的存在以及nscannedn的差異指示該查詢未使用最佳索引。在這種情況下,似乎需要進行收集掃描。您可以通過在您的sort條件中包含索引鍵來緩解此問題。從我的測試:

db.posts.find({hashtags: /^noticias/ }).limit(15).sort({hashtags:1, rank : -1}).explain() 

不需要掃描和秩序,並返回n和你正在尋找的記錄數的nscanned。這也意味着對hashtags密鑰進行排序,這對您可能有用或不可用,但應該提高查詢的性能。

+0

謝謝,那真的有竅門。另外值得注意的是,索引邊界是從第一個正則表達式推斷出來的,以防您添加多個。例如,這個查詢: 'db.posts.find({「$ and」:[{hashtags:/^manana /},{hashtags:/^noticias/}]}}.sort({'hashtags': 1,'rank': - 1})。limit(10).explain()' 將在manana上有索引界限,並且可能會有不同的表現。在我的情況下,排序正則表達式查詢按字母順序產生更好的性能 – Darius