6

次のようなクエリがあるとします。

db.things.find({
  deleted: false,
  type: 'thing',
  $or: [{
    'creator._id': someid
  }, {
    'parent._id': someid
  }, {
    'somerelation._id': someid
  }]
}).sort({
  'date.created': -1
})

つまり、これら 3 つの条件のいずれかを満たすドキュメントを検索し、新しい順に並べ替えたいということです。ただし、$or クエリは、並べ替えと共に使用する場合、並列でインデックスを使用しません。では、このクエリにどのようにインデックスを付けるのでしょうか?

http://docs.mongodb.org/manual/core/indexes/#index-behaviors-and-limitations

次の選択性を想定できます。

  • deleted- 99%
  • type- 25%
  • creator._id, parent._id, somerelation._id- < 1%
4

4 に答える 4

5

このクエリには複数のインデックスが必要になります。そのことに疑いの余地はありません。

問題は、どのインデックスですか?

$orここで、MongoDB クエリ オプティマイザーのバグにより、インデックスを使用して最適な方法でデータをカーディナルに並べ替えることができないことを考慮する必要があります: https://jira.mongodb.org/browse/SERVER- 1205年

$orしたがって、ソートでパフォーマンスの問題が発生し、ソート フィールドを$or句のインデックスに配置しても役に立たないことがわかります。

したがって、これを考慮して、最初に必要なインデックスは、作成している基本クエリをカバーするものです。@Leonidが言ったように、これを複合インデックスにすることができますが、彼が行った順序では行いません。代わりに、次のようにします。

db.col.ensureIndex({type:-1,deleted:-1,date.created:-1})

deleted選択性が非常に低いため、フィールドがインデックスに含まれているかどうかはまったくわかりません。実際には、パフォーマンスの低い操作を作成する可能性があります (これは SQL を含むほとんどのデータベースに当てはまります)。この部分は、ユーザーによるテストが必要です。たぶん、フィールドは最後にする必要があります(?)。

インデックスの順序については、やはり推測です。並べ替えが DESC であるため、すべてのフィールドに DESC を指定しましたが、explainここでは自分でこれを行う必要があります。

したがって、クエリのマスター句を処理できるはずです。次に、それらの s に対処し$orます。

それぞれ$orが個別にインデックスを使用し、MongoDB クエリ オプティマイザーはそれらが完全に個別のクエリであるかのように個別にインデックスを検索します。 /manual/core/indexes/#compound-indexes ) は、それらがプレフィックスで機能することです (ここでのメモの例: http://docs.mongodb.org/manual/core/indexes/#id5 )。したがって、作成することはできません3 つの句すべてをカバーする単一の複合インデックスであるため、$or(上記のバグを考慮して) でインデックスを宣言するより最適な方法は次のとおりです。

db.col.ensureindex({creator._id:1});
db.col.ensureindex({aprent._id:1});
db.col.ensureindex({somrelation._id:1});

クエリに最適なインデックスの作成を開始できるはずです。

ただし、これは自分でテストする必要があることを強調しておきます。

于 2013-02-13T18:47:15.580 に答える
3

Mongodb はクエリごとに 1 つのインデックスしか使用できないため、someidインデックスを使用してモデル内でクエリを実行する方法がわかりません。

したがって、最善のアプローチは、このタスクに特別なフィールドを追加することです。

ids = [creator._id, parent._id, somerelation._id]

$orこの場合、演算子を使用せずにクエリを実行できます。

db.things.find({
  deleted: false,
  type: 'thing',
  ids: someid
}).sort({
  'date.created': -1
})

この場合、インデックスは次のようになります。

{deleted:1, type:1, ids:1, 'date.created': -1}
于 2013-02-13T11:35:43.427 に答える
1

スキーマを柔軟に調整できる場合は、creator._id、parent._id、relation._idを保持する新しいフィールドassociatedIds:[]を追加することをお勧めします。対応するメインフィールドを更新するときに、そのフィールドをアトミ​​ックに更新できます。 、ただし、このフィールドに複合インデックスを設定し、typeとcreated_dateを指定して、クエリで$またはを完全に不要にすることができます。

于 2013-02-18T17:51:44.730 に答える
0

indexing の要件を考慮して、 $or クエリと一緒に $orderBy 演算子を使用することをお勧めします。つまり、$or クエリで使用される $or 式の条件にインデックスを付けることができ、$orderBy で結果を並べ替えることができます。

例えば:

db.things.find({
         deleted: false,
         type: 'thing',
         $or: [{
               'creator._id': someid
              }, {
          'parent._id': someid
          }, {
          'somerelation._id': someid
          }]
        },{$orderBy:{'date.created': -1}})

上記のクエリでは、$or 式の各フィールドに、orderBy 基準で指定された並べ替えオブジェクトと組み合わせた複合インデックスが必要です。

例えば:

db.things.ensureIndex{'parent._id': 1,"date.created":-1}
and so on for other fields.

結果に「制限」を指定して、mongodb が大量のメモリ内ソートを実行しないようにすることをお勧めします。$orderBy 演算子の詳細については、こちらをご覧ください

于 2013-02-20T06:53:14.350 に答える