2

次のようなドキュメントがあるとします。

{
  _id: ObjectId("5260ca3a1606ed3e76bf3835"),
  event_id: "20131020_NFL_SF_TEN",
  team: {
    away: "SF",
    home: "TEN"
  }
}

アウェーチームまたはホームチームが「SF」のゲームを照会したいと考えています。そこで、インデックスを付けteam.awayteam.home$or クエリを実行し、サンフランシスコのすべてのゲームを検索します。

別のオプション:

{
  _id: ObjectId("5260ca3a1606ed3e76bf3835"),
  event_id: "20131020_NFL_SF_TEN",
  team: [
    {
      name: "SF",
      loc: "AWAY"
    },
    {
      name: "TEN",
      loc: "HOME"
    }
  ]
}

上記の配列では、team.name以前のように 2 つのインデックスの代わりにインデックスを配置できます。次にteam.name、「SF」を含むゲームをクエリします。

どのクエリがより効率的ですか? ありがとう!

4

1 に答える 1

2

の単一インデックスで指定した2番目の例を使用したいと思うでしょうteam.name

オペレーターを操作する際に知っておく必要のある特別な考慮事項がいくつかあります$orドキュメントからの引用(いくつかの追加のフォーマットを含む):

クエリでインデックスを使用する場合$orは、クエリの各句が$or並行して実行されることに注意してください。これらの句は、それぞれ独自のインデックスを使用できます。

db.inventory.find ( { $or: [ { price: 1.99 }, { sale: true } ] } )

このクエリで は、複合インデックスではなく、 price:db.inventory.ensureIndex({ price: 1 }に1 つのインデックスを作成
し、sale: に別のインデックスを作成します。db.inventory.ensureIndex({ sale: 1 } )

最初の例を考慮に入れると、特にクエリを実行しないフィールドにインデックスを付けることはあまり意味がありません。SFがアウェイ ゲームでプレーするかホーム ゲームでプレーするかは気にしないと言うときは、常にaway フィールドの両方homeをクエリに含めるため、クエリする必要があるのは 1 つの値だけである 2 つのインデックスを使用しています - SF


この段階で、ドキュメントのフォーマットを考えるときは、クエリの大部分を常に考慮する必要があることに言及するのが適切であるように思われます。最も頻繁に実行する予定のクエリについて考え、それに応じてドキュメントを作成します。すべての可能性を解決しようとするよりも、可能な限り 80% のケースを処理することをお勧めします (全体的なパフォーマンスが低下する可能性があります)。


あなたが言ったように、ネストされたドキュメントの2番目の例を見ると、1つのインデックスのみを使用する必要があります(サーバーの貴重なスペースを節約します)。

$orドキュメントからのより関連性の高い引用(ここでも書式設定が追加されています):

また、クエリのメソッドで$or演算子を使用する場合、クエリはフィールドのインデックスを使用しません。上記のクエリにメソッドを 追加する次のクエリを検討してください。sort()$orsort()

db.inventory.find ({ $or: [{ price: 1.99 }, { sale: true }] }).sort({item:1})

この変更されたクエリは、 のインデックスも のインデックスも使用しません。pricesale

そこで質問なのですが、この機能を使用する予定はありsort()ますか? 答えが「はい」の場合、インデックスが役に立たなくなる可能性があることに注意してください。:(


ここから得られるのは、ほとんど「場合による!」ということです。実行する予定のクエリを検討し、使用予測に従って、どのドキュメント構造とインデックスが最も有益であるかを検討してください。

于 2013-10-20T21:36:00.020 に答える