2013-12-10 44 views
0

剖析查詢速度慢,我發現很奇怪的東西:對於下列操作整個集合進行了掃描(33061個文檔)即使是在查詢參數family_id索引:

{ 
    "ts" : ISODate("2013-11-27T10:20:26.103Z"), 
    "op" : "query", 
    "ns" : "mydb.zones", 
    "query" : { 
     "$query" : { 
      "family_id" : ObjectId("52812295ea84d249934f3d12") 
     }, 
     "$orderby" : { 
      "$natural" : 1 
     } 
    }, 
    "ntoreturn" : 20, 
    "ntoskip" : 0, 
    "nscanned" : 33061, 
    "keyUpdates" : 0, 
    "numYield" : 91, 
    "lockStats" : { 
     "timeLockedMicros" : { 
      "r" : NumberLong(83271), 
      "w" : NumberLong(0) 
     }, 
     "timeAcquiringMicros" : { 
      "r" : NumberLong(388988), 
      "w" : NumberLong(22362) 
     } 
    }, 
    "nreturned" : 7, 
    "responseLength" : 2863, 
    "millis" : 393, 
    "client" : "127.0.0.1", 
    "user" : "mydb" 
} 

後一些谷歌搜索無果後我發現刪除"$orderby": { "$natural" : 1}查詢速度非常快,只掃描了7個文檔而不是33061.所以我假設在我的情況下使用$orderby確實避免使用family_id上的索引。奇怪的是,在任何一種情況下,結果順序都沒有什麼不同。據我瞭解$自然順序是使用"$orderby": { "$natural" : 1}或沒有明確的順序是同義詞。另一個非常有趣的觀察是,這個問題不會出現在封頂收集!如果不使用任何排序/排序,不應該產生的順序在磁盤上的順序,即$natural爲了

  1. 出現此問題的以下幾個問題?

  2. 我可以創建一個自然排序的(複合)索引嗎?
  3. 如何反轉使用索引的簡單查詢的順序,以及沒有嚴重性能損失的不排序?
  4. 使用查詢參數和orderby時,幕後會發生什麼?爲什麼這不會發生在封頂集合?我想了解這種奇怪的行爲。
  5. 上述問題的答案與是否使用分片/複製無關嗎?查詢多個分片的自然順序是什麼?

注意我正在使用MongoDB 2.2。有與此問題相關的票證:https://jira.mongodb.org/browse/SERVER-5672。雖然看起來在票證中,問題發生在封頂集合中,我無法證實(可能是由於不同的mongo版本)。

回答

1

據我瞭解$自然順序,它使用 「$ orderby」:{「$ natural」:1}或者沒有明確的順序是同義詞。

這是$自然秩序的錯誤說明。 MongoDB在磁盤上以某種順序存儲記錄,並通過雙向鏈表追蹤它們。 $自然順序是您在遍歷鏈表時獲得的順序。但是,如果你指定$自然,那你總是會得到 - 而不是隨機的順序,而不是插入順序,而不是物理磁盤順序,而是「邏輯」磁盤順序 - 順序出現遍歷時鏈表。

如果不使用任何排序/排序,那麼結果順序應不是 磁盤上的順序,即$自然順序?

是的,假設你明白「磁盤順序」不是嚴格的物理順序,它的順序是它們在鏈接的記錄列表中。

我可以創建一個自然排序的(複合索引)嗎?

我不知道你的意思是自然排序 - 如果你在查詢過程中使用索引,文檔將按索引順序遍歷,而不是以$自然順序遍歷。

如何反轉使用索引的簡單查詢的排序並且沒有嚴重的性能損失沒有排序?

你不能 - 如果你正在使用一個索引,那麼你會得到索引順序記錄 - 你的選擇是讓他們的順序,依次反向或建立複合索引,你指數您正在搜索的字段您要排序的字段。

使用查詢參數和orderby時幕後會發生什麼?爲什麼這不會發生在封頂集合?我想了解這種奇怪的行爲。

會發生什麼取決於可用的索引,但查詢優化器會嘗試使用有助於篩選和排序的索引 - 如果這不可行,它將選擇具有最佳實際性能的索引。

上述問題的答案獨立於您是否使用 分片/複製與否?通過 多個分片查詢的自然順序是什麼?

這是來自每個單獨碎片的$自然順序的一些非確定性合併。

+0

嗯,也許文檔應該說更多關於你剛纔提到的,以及我記得被eliot告知mongodb返回查找順序':/'當我問你是否可以依靠訂單總是靜態的 – Sammaye

+1

你只能依賴於它是靜態的,如果你的數據庫是靜態的 - 也就是完全不變的 - 這不會是一個數據庫的太多,是嗎?你應該*不*依賴查找順序(又名$自然順序)是可預測的,因爲當你做更多的寫操作時,$自然順序可以並且將會改變。 –