2019回答
この回答はMongoDB4.2用です
質問と皆さんの間の議論を読んだ後、問題は解決したと思いますが、それでも最適化はMongoDBを使用しているすべての人に共通の問題です。
同じ問題に直面しました。クエリを最適化するためのヒントを次に示します。
私が間違っている場合は訂正してください:)
1。コレクションにインデックスを追加
インデックスは、コレクションのデータセットを簡単にトラバースできる形式で保存できるデータ構造であるため、クエリをすばやく実行する上で重要な役割を果たします。クエリは、MongoDBのインデックスを使用して効率的に実行されます。
必要に応じて、さまざまなタイプのインデックスを作成できます。インデックスの詳細については、MongoDBの公式ドキュメントをご覧ください。
2。パイプラインの最適化
- 常に$projectの前に$matchを使用する 、フィルターが次のステージから余分なドキュメントとフィールドを削除するため。
- 常に覚えておいてください。インデックスは$matchと$sortによって使用されます 。したがって、ドキュメントを並べ替えたりフィルタリングしたりするフィールドにインデックスを追加してみてください。
- クエリでこのシーケンスを維持するようにしてください。$limitの前に$sortを使用してください $ sort + $ limit +$skipのように。 $ sortはインデックスを利用し、MongoDBがクエリの実行中に必要なクエリプランを選択できるようにするためです。
- 常に$skipの前に$limitを使用 ドキュメントを制限するためにスキップが適用されるようにします。
- $projectを使用 次の段階で必要なデータのみを返します。
-
常に$lookupのforeignField属性にインデックスを作成します 。また、ルックアップによって配列が生成されるため、通常、次の段階で配列を巻き戻します。したがって、次の段階で巻き戻すのではなく、ルックアップ内で次のように巻き戻します。
{ $lookup: { from: "Collection", as: "resultingArrays", localField: "x", foreignField: "y", unwinding: { preserveNullAndEmptyArrays: false }
}}
-
allowDiskUseを使用します 集約では、集約操作を使用して、データベースパスディレクトリの_tmpサブディレクトリにデータを書き込むことができます。一時ディレクトリで大規模なクエリを実行するために使用されます。例:
db.orders.aggregate( [ { $match: { status: "A" } }, { $group: { _id: "$uid", total: { $sum: 1 } } }, { $sort: { total: -1 } } ], { allowDiskUse: true }, )
3。インデックスを再構築する
インデックスを頻繁に作成および削除する場合は、インデックスを再構築してください。これは、MongoDBが以前に保存されたクエリプランを更新するのに役立ちます。キャッシュは、必要なクエリプランを引き継ぎ続けます。信じてください、その問題は最悪です:(
4。不要なインデックスを削除する
インデックスが多すぎると、タスクとともにインデックスを作成する必要があるため、作成、更新、および削除操作に時間がかかりすぎます。したがって、それらを削除すると非常に役立ちます。
5。ドキュメントの制限
実際のシナリオでは、データベースに存在する完全なデータをフェッチすることは役に立ちません。また、それを表示できないか、ユーザーが完全にフェッチされたデータを読み取ることができません。したがって、完全なデータをフェッチする代わりに、データをチャンクでフェッチします。これは、あなたとクライアントの両方がそのデータを監視するのに役立ちます。
最後に、MongoDBによって選択された実行プランを監視することは、主要な問題を理解するのに役立ちます。したがって、$explainはそれを理解するのに役立ちます。
この要約が皆さんのお役に立てば幸いです。見逃した点があれば、遠慮なく新しい点を提案してください。私も追加します。