Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2008/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 是否正确索引数组字段?_Mongodb - Fatal编程技术网

Mongodb 是否正确索引数组字段?

Mongodb 是否正确索引数组字段?,mongodb,Mongodb,我正在使用具有以下文档设计的数据库: { 'email': 'a@b.com', 'credentials': [{ 'type': 'password', 'content': 'hashedpassword' }, { 'type': 'oauth2', 'content': 'token' }] } 我已索引了{credentials.type:1,credentia

我正在使用具有以下文档设计的数据库:

{
    'email':    'a@b.com',
    'credentials': [{
        'type':     'password',
        'content':  'hashedpassword'
    }, {
        'type':     'oauth2',
        'content':  'token'
    }]
}
我已索引了
{credentials.type:1,credentials.content:1}
。它已被正确拾取,但在一个50k文档集合上的性能很差

以下是指示查询计划的日志:

[conn73] command database.users command: find {
    find: "users",
    filter: {
        credentials.type: "type",
        credentials.content: "content"
    },
    limit: 1,
    batchSize: 1,
    singleBatch: true
}
planSummary: IXSCAN {
    credentials.type: 1,
    credentials.content: 1
}
keysExamined:20860
docsExamined:18109
cursorExhausted:1
keyUpdates:0
writeConflicts:0
numYields:163
nreturned:1
reslen:455
locks:{
    Global: {
        acquireCount: {
            r: 328
        }
    },
    Database: {
        acquireCount: {
            r: 164
        }
    },
    Collection: {
        acquireCount: {
            r: 164
        }
    }
}
protocol:op_query
331ms
我注意到我有大量的密钥被检查和文档被检查。我知道mongodb能够将所有值放入数组中以构建索引。为什么要扫描这么多钥匙

我确实有高并发访问,但只能读

下面是查询的explain()结果:

> db.users.find({'credentials.type': 'abc', 'credentials.content': 'def'}).explain()
{
    "queryPlanner" : {
        "plannerVersion" : 1,
        "namespace" : "net.users",
        "indexFilterSet" : false,
        "parsedQuery" : {
            "$and" : [
                {
                    "credentials.type" : {
                        "$eq" : "abc"
                    }
                },
                {
                    "credentials.content" : {
                        "$eq" : "def"
                    }
                }
            ]
        },
        "winningPlan" : {
            "stage" : "FETCH",
            "filter" : {
                "credentials.content" : {
                    "$eq" : "def"
                }
            },
            "inputStage" : {
                "stage" : "IXSCAN",
                "keyPattern" : {
                    "credentials.type" : 1,
                    "credentials.content" : 1
                },
                "indexName" : "credentials.type_1_credentials.content_1",
                "isMultiKey" : true,
                "isUnique" : false,
                "isSparse" : false,
                "isPartial" : false,
                "indexVersion" : 1,
                "direction" : "forward",
                "indexBounds" : {
                    "credentials.type" : [
                        "[\"abc\", \"abc\"]"
                    ],
                    "credentials.content" : [
                        "[MinKey, MaxKey]"
                    ]
                }
            }
        },
        "rejectedPlans" : [ ]
    },
    "serverInfo" : {
        "host" : "localhost",
        "port" : 27017,
        "version" : "3.2.11",
        "gitVersion" : "009580ad490190ba33d1c6253ebd8d91808923e4"
    },
    "ok" : 1
}

我正在运行mongodb v3.2.11。如何正确优化此查询?我是否应该更改文档设计?

您可以尝试将凭据分离到不同的文档中

例如:

{
    'email':    'a@b.com',
    'credentialType':     'password',
    'credentialContent':  'hashedpassword'
}

{
     'email':    'a@b.com',
     'credentialType':     'oauth2',
     'credentialContent':  'token'
}
并创建凭证类型和凭证内容的索引


这样,您将拥有更多文档,但索引更清晰。您的查询将运行得更快。因为它不需要处理对象数组。

多亏了Sergiu Zaharie的提示,我能够重新审视索引问题

事实证明,由于“credentials.type”都是相似的,“credentials.content”都是不同的,所以我应该首先将复合索引放在“credentials.content”上


换句话说,
{credentials.content:1,credentials.type:1}
就是这里的答案。

是否有关于数组对象索引应该如何变慢的参考资料?除了现有的索引{credentials.type:1,credentials.content:1}之外,您还可以在{credentials:1}上建立一个索引。您能否详细说明查询和所需的结果文档(s) ?也请发布查询。解释()@SergiuZaharie我已经更新,加入了查询解释。当使用计算机索引时,查询中字段的顺序并不重要,它只影响排序。这里的示例看起来,对唯一字段进行索引比对具有少量选择的字段进行索引更能提高性能。我最初认为顺序无关紧要,我也没有其他地方也学到了。我假设索引字段是串联的,但情况也并非如此。看来索引中的第一个字段非常重要,最好接近唯一。