2017-02-19 76 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能够使用正确的索引。