web-dev-qa-db-ja.com

MongoDB Findパフォーマンス:単一の複合インデックスVS 2つの単一フィールドインデックス

MongoDb 3.4で使用するインデックス作成戦略に関するアドバイスを探しています。

次の形のドキュメントのpeopleコレクションがあるとします:

_{
    _id: 10,
    name: "Bob",
    age: 32,
    profession: "Hacker"
}
_

コレクションを照会するWeb APIが公開されており、唯一の可能なフィルターはnameまたはであると想像してみましょう年齢
APIのサンプルコールは次のようになります。_http://myAwesomeWebSite/people?name="Bob"&age=25_

このような呼び出しは、次のクエリで変換されます:db.people.find({name: "Bob", age: 25})

シナリオをより明確にするために、次のことを考慮してください。

  • フィールドnameはすでにドキュメント内にあり、そのフィールドにはすでにインデックスがあります
  • アプリケーションのいくつかの新機能により、新しいフィールドageを追加します。
  • データベースは上記のWeb APIを介してのみアクセスでき、最も重要な要件は超高速Web APIを公開することです
  • web APIへのすべての呼び出しはフィルターを適用しますフィールド名と年齢の両方で(別の言い方をすれば、Web APIへのすべての呼び出しは同じパターンを持ちます。これは上に示したものです)

ただし、次のインデックスのどれが最高のパフォーマンスを提供するかを決定する必要があります。

  • 1つの複合インデックス:_{name: 1, age: 1}_
  • 2つの単一フィールドインデックス:_{name: 1}_および_{age: 1}_

いくつかの簡単なテストによると、単一の複合インデックスは、2つの単一フィールドインデックスよりもはるかにパフォーマンスが高いのようです。

Mongoシェルを介して単一のクエリを実行することにより、explain()メソッドは、単一の複合インデックスを使用すると、2つの単一フィールドインデックスを使用するよりもほぼ10倍速くデータベースをクエリできることを示唆します。

この違いは、mongo Shellを介して単一のクエリを実行する代わりに、nodejs Webアプリケーションの2つの異なるURLに対して複数の呼び出しが行われる、より現実的なシナリオではそれほど劇的ではないようです両方のURLはデータベースへのクエリを実行し、フェッチされたデータをJSON配列として返します。1つは単一の複合インデックスを持つコレクションを使用し、もう1つは2つの単一フィールドインデックスを持つコレクションを使用します(両方のコレクションはまったく同じドキュメントを持ちます)。
このテストでは、パフォーマンスに関しては単一の複合インデックスが依然として最良の選択であるように見えますが、今回はその差はそれほど顕著ではありません。

テスト結果によると、単一複合インデックスのアプローチを使用することを検討しています。

誰もこのトピックについて経験がありますか?重要な考慮事項がありませんか(おそらく大きな複合インデックスのいくつかの欠点)?

22
Enrico Massone

limit()またはsort()または空想が適用されていない)単純な標準クエリで、2つのフィールドにフィルター条件がある場合(例:nameおよびage)例)、結果のドキュメントを見つけるために、MongoDBは次のいずれかを行います:

  1. 完全なcollection scanを実行します(コレクション全体のすべてのドキュメントを読み取り、BSONを解析し、問題の値を見つけ、入力に対してテストし、return /各ドキュメントを破棄):これはスーパーI/Oが激しいため、低速です。
  2. フィールドの1つを保持する1つのインデックスを使用します(インデックスツリーを使用して、関連するドキュメントのサブセットを見つけ、続いてそれらのスキャンを行います):データ分布に応じて/ index 選択性 これは非常に高速であるか、ほとんど利点がありません(30年から40年の間の数百万人のデータセットでageのインデックスを想像してください->すべてのルックアップはまだ得られます無限の数のドキュメント)。
  3. 問題の両方のフィールドを一緒に含む2つのインデックスを使用します(両方のインデックスをロードし、キールックアップを実行してから、 交差 を計算します結果):繰り返しますが、データの分布によっては、パフォーマンスが向上する場合としない場合があります。ただし、ほとんどの場合、#2よりも高速です。ただし、実際に#4の10倍遅くなったら驚かれるでしょう(おっしゃるように)。
  4. 複合インデックスを使用します(2回の後続のキールックアップがすぐに必要なドキュメントにつながります):これはすべての最速のオプションになります適切なドキュメントを取得するために必要な操作が最も少なくて済むことを考えると、再利用の最大レベル(これにより影響を受けないパフォーマンスではない)を確保するために、一般的に最初に最も選択的なフィールドから開始する必要があります。したがって、おそらくnameではなくage多くの人がage(より高い選択性)と同じname(非常に低い選択性)を持っていることを考えると。ただし、その選択は、具体的なシナリオと、データベースに対して実行するクエリによっても異なります。 Webには、特定の状況のさまざまな側面を考慮して複合インデックスを最適に定義する方法に関する非常に良い記事があります。 https://emptysqua.re/blog/optimizing-mongodb-compound-indexes =

考慮すべきその他の側面は次のとおりです。インデックスの更新には一定の価格がかかります。ただし、必要なのが未加工の読み取り速度であり、たまに数回しか更新しない場合は、より多くの/より大きなインデックスを使用する必要があります。

最後に大事なことを言い忘れていません(!)よく使いすぎる収益のアドバイス:実際のデータと、場合によっては現実的な負荷シナリオを使用して、システムを徹底的にプロファイルします。また、時間とともにデータ/システムが変化しても測定を続けます。

追加の読み取り: https://docs.mongodb.com/manual/core/query-optimization/index.html

https://dba.stackexchange.com/questions/158240/mongodb-index-intersection-does-not-eliminate-the-need-for-creating-compound-in

インデックスの交差と複合インデックス?

mongodb compundインデックスとインデックスインターセクト

MongoDBのパフォーマンスの観点から、複合インデックスの順序はどのように重要ですか?

MongoDBでは、大規模なクエリを使用しています。複合インデックスまたは単一インデックスを作成する方法です。したがって、応答時間が向上します

26
dnickless