有一些问题与您的查询和索引:
1 $或使用索引不同
MongoDB中只使用一个索引的查询,处理涉及$or
子句的查询的除外。来自Indexing Strategies页面:
通常,MongoDB只使用一个索引来完成大多数查询。然而,$或查询的每个子句可以使用不同的指标
同样来自$or Clauses and Indexes页:
也就是说,MongoDB的使用索引来评估一个$或表达式,所有条款在$或表达式中必须由索引支持。
关于您的查询,你可以尝试重新安排查询,使$or
条款顶级子句:
{$or: [
{"palabra": {...}, "_p_pais": {...} },
{"palabra": {...}, "languageCodeTatoeba": {...}}
]}
在这种形式下,MongoDB的可以用两个指标:
- 化合物指数为
palabra
和_p_pais
条款和
- 化合物指数为
palabra
和languageCodeTatoeba
条款
请使用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
有两个问题与这组指标:
- 在这些指标,有些是多余的。例如,
languageCodeTatoeba_1
(上升指数)和languageCodeTatoeba_-1
(下降指数)实际上是相同的指数。其中一个可以被删除而不会对查询性能产生任何影响。
- 很多索引是另一个的前缀。例如,
palabra_-1
和palabra_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能够使用正确的索引。
您可以发布快速查询的(。或两者)的'.explain()'吗? – Lucas