1

私は約 30,000 個のアイテムのコレクションを持っており、そのすべてに Program という要素があります。「プログラム」は複合インデックスの最初の部分であるため、特定のプログラム値を持つアイテムの検索は非常に高速です。範囲クエリを実行するのも高速です。たとえば、次のようになります。

db.MyCollection.find(
{ $and: [ { Program: { "$gte" : "K", "$lt" : "L" } }, 
{ Program: { "$gte" : "X", "$lt" : "Y" } } ] }).count();

上記のクエリは、重複しない 2 つの範囲 (KL) と (XY)) の重複をクエリしているため、結果を返しません。左の範囲 (KL) には、約 7K のアイテムが含まれています。

ただし、2 番目の「and」句を「where」式に置き換えると、クエリの実行に時間がかかります。

db.MyCollection.find(
{ $and: [ { Program: { "$gte" : "K", "$lt" : "L" } }, { "$where" : "this.Program == \"Z\"" } ] }).count();

ご覧のとおり、上記のクエリも空の結果セットを返すはずです (範囲 KL は Program=="Z" と組み合わされています)。「where」のパフォーマンスが遅いことは承知していますが、Mongo は最初に left 句を評価して潜在的な結果セットを削減し (約 7K 項目になります)、「where」チェックを適用するべきではありませんか? その場合、この操作の実行中に約 3 GB の RAM を消費する Mongo サービスを使用しているマシンでは、数千のアイテムの処理に数分ではなく数秒かかるのではないでしょうか? 比較的小さなコレクションには重すぎるように見えます。

4

1 に答える 1

3

あなたができることがいくつかあります -

  1. explain()クエリで何が起こっているかを確認するために使用します。ここexplain()に記載されています。$explain 演算子を使用して、クエリを返すために使用されるプロセスとインデックスを説明するドキュメントを返します。例えば ​​-

    デシベル.コレクション.find(クエリ).explain()

  2. それでも十分な情報が返されない場合は、Database Profilerを使用して調べることができます。ただし、これは無料ではなく、負荷自体がかかることに注意してください。このページには、クエリ パフォーマンスの最適化に関する基本的な注意事項も記載されています。

  3. ただし、あなたの場合、すべて $where 演算子に要約されます。

    $where は JavaScript を評価し、インデックスを利用できません。したがって、標準の MongoDB 演算子 ($gt、$in など) を使用してクエリを表現すると、クエリのパフォーマンスが向上します。

    一般に、別の演算子を使用してクエリを表現できない場合にのみ、$where を使用する必要があります。$where を使用する必要がある場合は、結果セットをフィルター処理するために、少なくとも 1 つの他の標準クエリ演算子を含めるようにしてください。$where を単独で使用するには、テーブル スキャンが必要です。$where は、Map Reduce と同様に、同時実行性を制限します。

explain()参考までに:からの出力について注意すべき点がいくつかあります。

  • ntoreturnクライアントがクエリから返すよう要求したオブジェクトの数。たとえば、findOne()nreturn をlimit()適切な制限に設定します。ゼロは制限がないことを示します。
  • queryクエリ仕様の詳細。
  • nscanned操作の実行中にスキャンされたオブジェクトの数。
  • reslenクエリ結果の長さ (バイト単位)。
  • nreturnedクエリから返されたオブジェクトの数。
于 2012-07-26T14:21:18.560 に答える