mongoDBプロジェクションはパフォーマンスにどのように影響しますか?


10

MongoDBドキュメンテーションからそれは言及されています:

ドキュメントのフィールドのサブセットのみが必要な場合、必要なフィールドのみを返すことでパフォーマンスを向上させることができます

フィルタリングフィールドはパフォーマンスにどのように影響しますか?パフォーマンスは、ネットワークを介して送信されるデータのサイズに関連していますか?またはメモリに保持されるデータのサイズ?このパフォーマンスはどの程度正確に改善されていますか?ドキュメントに記載されているこのパフォーマンスとは何ですか?

MongoDBクエリが遅い。サブセットを返すと、遅いクエリに影響がありますか(フィールドに複合インデックスがあります)?


コードがなければ、あなたを提案することはできません。「MongoDB」プロジェクションクエリのパフォーマンスに実際に何が影響するか。少なくともあなたがコードに言及することは常により良いことです。
Md Haidar Ali Khan

@MdHaidarAliKhanそれはコードと私のペイロードについてではありません。mongoDBがフィルタリングがパフォーマンスに影響を与えると言っている理由を知りたいだけですか?このパフォーマンスはどのような観点から測定されていますか?たとえば、データやディスクIOが少ないため(たとえば)、Mongoのメモリ使用量を削減できます。
ALH

mongoDBがフィルタリングがパフォーマンスに影響を与えると言っている理由を知りたいだけですか?まあ、プロジェクションを使用して必要なデータのみを返す、つまり必要なフィールドだけを返すことでパフォーマンスを向上できるということです。たとえば、db.posts.find({}、{})。sort({})です。
Md Haidar Ali Khan

たとえば、データやディスクIO(たとえば)が少ないなどの理由で、Mongoのメモリ使用量に役立ちますか。環境内のどのMongoDBバージョンとオペレーティングシステムを更新できますか?
Md Haidar Ali Khan

@MdHaidarAliKhan OSはDebian 8MongoDB 3.6.2
ALH

回答:


15

デフォルトでは、クエリは一致するドキュメントのすべてのフィールドを返します。すべてのフィールドが必要な場合、完全なドキュメントを返す方が、サーバーに投影基準を使用して結果セットを操作させるよりも効率的です。

ただし、プロジェクションを使用してクエリ結果から返されるフィールド制限すると、次のようにしてパフォーマンスを向上させることができます

  • クエリ結果から不要なフィールドを削除する(ネットワーク帯域幅を節約する)
  • 結果フィールドを制限して対象クエリを実現する(完全なドキュメントをフェッチせずにインデックス付きクエリ結果を返す)

プロジェクションを使用して未使用のフィールドを削除する場合、MongoDBサーバーは各ドキュメント全体をメモリにフェッチし(まだそこにない場合)、結果をフィルターして返す必要があります。このプロジェクションを使用しても、MongoDBサーバーのメモリ使用量やワーキングセットは削減されませんが、データモデルと予測されるフィールドに応じて、クエリ結果のネットワーク帯域幅を大幅に節約できます。

対象クエリは、クエリ結果のすべての要求されたフィールドが使用されるインデックスに含まれる特殊なケースであるため、サーバーはドキュメント全体をフェッチする必要はありません。カバーされたクエリは、(ドキュメントのフェッチを回避することにより)パフォーマンスとメモリ使用量(他のクエリが同じドキュメントのフェッチを必要としない場合)を改善できます。

mongoシェルを介したデモ目的で、次のようなドキュメントがあるとします。

db.data.insert({
    a: 'webscale',
    b: new Array(10*1024*1024).join('z')
})

フィールドbは、値の選択(またはこの場合は非常に長い文字列)を表す場合があります。

次に、{a:1}ユースケースによってクエリされる一般的に使用されるフィールドであるインデックスを作成します。

db.data.createIndex({a:1})

findOne()射影基準のない単純なものは、約10MBのクエリ結果を返します。

> bsonsize(db.data.findOne({}))
10485805

プロジェクション{a:1}を追加すると、出力がフィールドaとドキュメント_id(デフォルトで含まれています)に制限されます。MongoDBサーバーは引き続き2つのフィールドを選択するために10 MBのドキュメントを操作していますが、クエリ結果は33バイトのみになっています。

> bsonsize(db.data.findOne({}, {a:1}))
33

_id値を見つけるにはドキュメント全体をフェッチする必要があるため、このクエリは対象外です。_idフィールドは、それが文書の一意の識別子であるため、デフォルトでは、クエリ結果に含まれていますが、_id明示的に追加しない限り、二次インデックスに含まれません。

結果のtotalDocsExaminedtotalKeysExaminedメトリックは、explain()調査されたドキュメントとインデックスキーの数を示します。

 > db.data.find(
     {a:'webscale'}, 
     {a:1}
 ).explain('executionStats').executionStats.totalDocsExamined
 > 1

このクエリは、射影を使用して_idフィールドを除外し、{a:1}インデックスのみを使用して対象クエリを実行することで改善できます。カバーされたクエリは、最大10MBのドキュメントをメモリにフェッチする必要がなくなったため、ネットワークとメモリの両方の使用において効率的になります。

 > db.data.find(
     {a:'webscale'},
     {a:1, _id:0}
 ).explain('executionStats').executionStats.totalDocsExamined
 0

 > bsonsize(db.data.findOne( {a:'webscale'},{a:1, _id:0}))
 21

MongoDBクエリが遅い。サブセットを返すと、遅いクエリに影響がありますか(フィールドに複合インデックスがあります)?

これは、特定のクエリ、サンプルドキュメント、および完全な説明出力のコンテキストなしでは答えられません。ただし、プロジェクションがある場合とない場合の同じクエリに対して、独自の環境でベンチマークを実行して結果を比較することもできます。予測によってクエリの実行時間全体(処理と結果の転送)に大幅なオーバーヘッドが追加される場合、これはデータモデルが改善される可能性があることを強く示唆しています。

クエリが遅い理由が明確でない場合は、調査する特定の詳細を含む新しい質問を投稿するのが最善です。


1
問題の徹底的な説明に本当に感謝しています。私の応答にはインデックス内よりもはるかに多くのデータがあるため、クエリをカバーすることは不可能のようです。私の主な質問はここです、あなたが見ていただければ幸いです:dba.stackexchange.com/questions/195065/…–
ALH

1

プロジェクションを使用すると、結果セットがインデックスから直接取得される状況を実現できます。

{x:1, y:1, z:1}x、y、zが_idでない複合インデックスがある場合{_id:0, x:1, y:1, z:1}_idは常に結果セットの一部として返されるため(投影されない場合)、エンジンはデータファイルを読み取って取得する必要があるため、投影する必要があります。これは、インデックスには_idの値がなく、値が格納されているドキュメントへのポインタのみであるためです。


_id返された応答から削除すると、RAMに収まりますか?それは役に立ちますか?
ALH 2018

1
MongoD(試行)を実行して、少なくともインデックスをメモリに保持します(データをできるだけ多く保持します)。クエリをインデックスから直接入力してプロジェクトを作成できる場合_id:0、結果はディスクからデータを読み取らずにRAMから完全に返されます。
JJussi
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.