web-dev-qa-db-ja.com

MongoDB $ lookupはインデックスを使用していません

2つのテーブル間で$ lookupを必要とするクエリを作成していますが、理解しているように、この結合をタイムリーに実行するには、foreignFieldにインデックスが必要です。ただし、フィールドにインデックスを追加した後でも、クエリは引き続きCOLLSCANにフォールバックします。

db.users.aggregate([
  {$lookup:{ from: "transactions", localField: '_id', foreignField: 'uid', as: 'transaction' }},
  { $match: { transaction: { "$size" : 0} } },
  { $count: "total"},
], { explain: true })

これは次を返します:

"queryPlanner" : {
    "plannerVersion" : 1,
    "namespace" : "test.users",
    "indexFilterSet" : false,
    "parsedQuery" : {

    },
    "winningPlan" : {
        "stage" : "COLLSCAN",
        "direction" : "forward"
    },
    "rejectedPlans" : [ ]
}

前述したように、トランザクションコレクションでidフィールドにインデックスが付けられています。

> db.transactions.getIndexes()
[
    {
        "v" : 1,
        "key" : {
            "_id" : 1
        },
        "name" : "_id_",
        "ns" : "test.transactions"
    },
    {
        "v" : 1,
        "key" : {
            "uid" : 1
        },
        "name" : "uid_1",
        "ns" : "test.transactions"
    }
]

クエリは、約700万のドキュメントのDBで実行されるのに数分かかります。 MongoDBv3.4.7を使用しています。私が間違っている可能性があることについて何か考えはありますか?前もって感謝します!

11
ashe540

"stage" : "COLLSCAN",$lookupをまったく参照していません。

その集約パイプラインの最初のステップは、「users」コレクションからすべてのドキュメントをフェッチすることです。そのためのフィルターはまったく提供されていないため、コレクションスキャンが最も効率的な方法です。

$ lookupステージは、他のクエリと同じように計画する必要があり、インデックスを使用する可能性があります。

2
Joe

集約パイプラインの最初のステージには、インデックス付きキーに対する$matchまたは$sortまたは$geoNearクエリがなく、$ matchステージでは、インデックスキーに対してクエリを実行しなかったためです。

ケース1:最初のステージでインデックス付きキーに対して$ matchを実行すると、WinningPlanステージは"FETCH"になります。 inputStage"IXSCAN"になります

"winningPlan" : {
    "stage" : "FETCH",
    "inputStage" : {
            "stage" : "IXSCAN",
        ...
    }
}

ケース2:最初のステージでインデックス付けされていないキーに対して$ matchを実行すると、WinningPlanステージは"COLLSCAN"になります。

"winningPlan" : {
    "stage" : "COLLSCAN"
}

ケース3:ルックアップ後にインデックスキーで$ matchを実行すると(クエリによると)、WinningPlanステージは"FETCH"およびinputStage"IXSCAN"になります。

ケース4:ルックアップ後に非インデックスキーで$ matchを実行した場合(実行しただけ)、WinningPlanステージは"COLLSCAN"

7Mレコードの場合、クエリでインデックスを使用する必要があります。 RAMに格納され、インデックス付きキーで$neまたは$ninを適切に使用できないため、あまり多くのインデックスを作成しないでください。

Mongodbドキュメント:集約パイプラインの最適化

Mongodbドキュメント:インデックス作成戦略

0
Ashutosh Sharma