Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MongoDB查询在使用$or运算符时变慢_Mongodb_Indexing_Mongodb Query - Fatal编程技术网

MongoDB查询在使用$or运算符时变慢

MongoDB查询在使用$or运算符时变慢,mongodb,indexing,mongodb-query,Mongodb,Indexing,Mongodb Query,我正试图对我的收藏Audios var querySlow = { "palabra": { $regex: "^" + keywords, "$options": "i" }, $or: [{ "_p_pais": { $in: interested_accents } }, {

我正试图对我的收藏
Audios

    var querySlow = {
        "palabra": {
            $regex: "^" + keywords,
            "$options": "i"
        },
        $or: [{
            "_p_pais": {
                $in: interested_accents
            }
        }, {
            "languageCodeTatoeba": {
                $in: interested_accents_tatoeba
            }
        }]
    }; // takes 20 seconds
这实际上是非常非常慢,但是如果我删除任何
$或
,它是非常非常快,例如:

    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()


实际上,我不知道如何管理索引,是否应该为此集合创建索引???

您的查询和索引存在一些问题:

1$或者使用不同的索引

MongoDB对一个查询只使用一个索引,涉及
$或
子句的查询除外。从页面:

通常,MongoDB只使用一个索引来完成大多数查询。但是,$or查询的每个子句可能使用不同的索引

另请参见本页:

也就是说,为了让MongoDB使用索引计算$or表达式,索引必须支持$or表达式中的所有子句

关于您的查询,您可以尝试重新安排查询,使
$或
子句成为顶级子句:

{$or: [
    {"palabra": {...}, "_p_pais": {...} },
    {"palabra": {...}, "languageCodeTatoeba": {...}}
]}
在这种形式下,MongoDB可以使用两个索引:

  • 带有
    palabra
    术语的复合索引,以及
  • 带有
    palabra
    languageCodeTatoeba
    术语的复合索引
请使用
explain(“executionStats”)
检查索引是否正确使用。您希望最小化的关键指标是文档数量(
nReturned
)与检查的文档/密钥总数之比。比率越接近1,查询的选择性越高,性能越好

例如,如果MongoDB必须检查1000个文档(
TotalDocsAdmined:1000
),但只返回10个文档(
nReturned:10
),那么您的查询不是很有选择性(即10/1000的比率)。理想的查询将具有接近或等于1的比率,例如,
nReturn:10,TotalDocsChecked: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_uu-1
    palabra_u-1在
    创建。可以删除
    palabra_uu1
    索引,因为它是在
  • 索引处创建的
    palabra_1_uu的前缀。请参阅该页了解更多详细信息
    粗略地看一下,您可以将索引列表调整为仅包含以下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。为什么从
    $或
    术语中删除一个子句会加快查询速度

    这是因为查询

    {"palabra": {...}, $or: [{"_p_pais": {...}}]}
    
    本质上与

    {"palabra": {...}, "_p_pais": {...}}
    
    {"palabra": {...}, "languageCodeTatoeba": {...}}
    
    假设您有一个复合索引,例如
    palabra_1_p_pais_1
    ,MongoDB将能够使用该索引

    同样地

    {"palabra": {...}, $or: [{"languageCodeTatoeba": {...}}]}
    
    本质上与

    {"palabra": {...}, "_p_pais": {...}}
    
    {"palabra": {...}, "languageCodeTatoeba": {...}}
    
    此查询可以使用集合中已有的
    \u p\u pais\u 1\u languageCodeTatoeba\u 1
    索引


    简而言之,这两个查询很快,因为您删除了
    $或
    子句,使MongoDB能够使用正确的索引。

    您可以发布快速查询的
    .explain()