2017-02-19 74 views
3

我試圖讓這個查詢到我的收藏時降低Audios

var querySlow = { 
     "palabra": { 
      $regex: "^" + keywords, 
      "$options": "i" 
     }, 
     $or: [{ 
      "_p_pais": { 
       $in: interested_accents 
      } 
     }, { 
      "languageCodeTatoeba": { 
       $in: interested_accents_tatoeba 
      } 
     }] 
    }; // takes 20 seconds 

這實際上是真的很慢但如果我刪除任何$or的,它是非常非常快,例如:

var queryFast1 = { 
     "palabra": { 
      $regex: "^" + keywords, 
      "$options": "i" 
     }, 
     $or: [{ 
      "_p_pais": { 
       $in: interested_accents 
      } 
     }] 
    }; // takes less than 1 second 

或本

var queryFast2 = { 
     "palabra": { 
      $regex: "^" + keywords, 
      "$options": "i" 
     }, 
     $or: [{ 
      "languageCodeTatoeba": { 
       $in: interested_accents_tatoeba 
      } 
     }] 
    }; // takes less than 1 second 

這是慢速查詢的.explain()

http://pastebin.com/nrhjB1wf

我居然不知道如何管理指標,我應該創建一個索引到此集合?

+0

您可以發佈快速查詢的(。或兩者)的'.explain()'嗎? – Lucas

回答

0

有一些問題與您的查詢和索引:

1 $或使用索引不同

MongoDB中只使用一個索引的查詢,處理涉及$or子句的查詢的除外。來自Indexing Strategies頁面:

通常,MongoDB只使用一個索引來完成大多數查詢。然而,$或查詢的每個子句可以使用不同的指標

同樣來自$or Clauses and Indexes頁:

也就是說,MongoDB的使用索引來評估一個$或表達式,所有條款在$或表達式中必須由索引支持。

關於您的查詢,你可以嘗試重新安排查詢,使$or條款頂級子句:

{$or: [ 
    {"palabra": {...}, "_p_pais": {...} }, 
    {"palabra": {...}, "languageCodeTatoeba": {...}} 
]} 

在這種形式下,MongoDB的可以用兩個指標:

  • 化合物指數爲palabra_p_pais條款和
  • 化合物指數爲palabralanguageCodeTatoeba條款

請使用explain("executionStats")檢查索引是否正確使用。您希望最小化的關鍵指標是文檔數量(nReturned)與檢查的總文檔/關鍵字數量。比率越接近1,查詢的選擇性越高,性能越好。例如,如果MongoDB必須檢查1000個文檔(totalDocsExamined: 1000),但只返回10個文檔(nReturned: 10),那麼您的查詢不是很有選擇性(即比例爲10/1000)。理想查詢的比例接近或等於1,例如nReturned: 10, totalDocsExamined: 10,比例1(10/10)。

有關explain()的更多信息,請訪問:

2.索引過多

有太多的指標可能會導致:

  • 查詢規劃器選擇次優索引,因爲它們都不知道要使用哪個索引,因爲它們看起來都一樣。
  • 相對較慢的插入/更新性能,因爲每次插入/更新索引中包含的字段也需要插入/更新索引。

從您發佈的解釋結果,你必須至少這些集合中的指標:

_p_pais_-1__p_user_-1__created_at_-1 
languageCodeTatoeba_1_lowercase_1 
languageCodeTatoeba_1 
languageCodeTatoeba_-1 
_p_pais_-1 
_p_pais_1_languageCodeTatoeba_1 
palabra_-1 
palabra_1__created_at_-1 

有兩個問題與這組指標:

  1. 在這些指標,有些是多餘的。例如,languageCodeTatoeba_1(上升指數)和languageCodeTatoeba_-1(下降指數)實際上是相同的指數。其中一個可以被刪除而不會對查詢性能產生任何影響。
  2. 很多索引是另一個的前綴。例如,palabra_-1palabra_1__created_at_palabra_-1索引可以被刪除,因爲它是palabra_1__created_at_索引的前綴。請參閱Compound Index: Prefix頁面瞭解更多詳情。

從粗略地看一眼,你可以到你的索引列表修剪到只包含這4個指標,而不是8:

_p_pais_-1__p_user_-1__created_at_-1 
languageCodeTatoeba_1_lowercase_1 
_p_pais_1_languageCodeTatoeba_1 
palabra_1__created_at_-1 

請參閱有關更多信息的索引以下鏈接:

3.爲什麼從長期$or取出一個條款加快了查詢

這是因爲查詢

{"palabra": {...}, $or: [{"_p_pais": {...}}]} 

是基本相同

{"palabra": {...}, "_p_pais": {...}} 

假設你有一個複合索引如palabra_1__p_pais_1,MongoDB將能夠使用該索引。

同樣,

{"palabra": {...}, $or: [{"languageCodeTatoeba": {...}}]} 

是基本相同

{"palabra": {...}, "languageCodeTatoeba": {...}} 

這種查詢可以使用_p_pais_1_languageCodeTatoeba_1指數,你已經有你的收藏。

總之,這兩個查詢都很快,因爲您刪除了$or子句,使MongoDB能夠使用正確的索引。