データベース管理に関連するタスクの中には、さまざまな戦略を採用することによってパフォーマンスを向上させることがあります。インデックス作成は、クエリ要求へのデータアクセスを容易にすることでスループット操作を改善するためのヒントの1つです。これは、クエリの処理時に必要なディスクアクセスの数を最小限に抑えることで実現します。 MongoDBでインデックスを使用しないと、データベースは完全なコレクションスキャンを実行します。つまり、発行されたクエリステートメントに一致するドキュメントを選択するために、コレクション内のすべてのドキュメントをスキャンします。明らかに、関係するドキュメントが非常に多い場合は特に、これには多くの時間がかかります。一言で言えば、インデックスはクエリの効率的な実行をサポートします。
MongoDBインデックス
多くのドキュメントをMongoDBコレクションに保存することを想定しているため、インデックスを使用して簡単にトラバースできるように、各ドキュメントのデータのごく一部を異なるパーティションに保存する方法を見つける必要があります。インデックスは特定のフィールド値を格納し、このデータをそのフィールドの値の順に並べ替えます。この順序付けにより、効率的なクエリマッチングと範囲ベースのクエリ操作がサポートされます。インデックスはコレクションレベルで定義され、コレクション内のドキュメントの任意のフィールドまたは埋め込みフィールドでサポートされます。
ドキュメントを作成するとき、MongoDBは、指定されていない場合、デフォルトで_idフィールドを割り当て、これをそのドキュメントの一意のインデックスにします。基本的に、これは、同じドキュメントがそのコレクションに複数挿入されないようにするためです。さらに、シャードクラスターの場合、シャードキーの選択の一部としてこの_idフィールドを使用することをお勧めします。そうしないと、エラーを回避するために_idフィールドにデータの一意性が必要になります。
コレクションのインデックスの作成
コレクションにデータを挿入し、フィールドをインデックスとして割り当てたい場合は、createIndexメソッドを使用してこれを実現できます。つまり
このjsonデータがあるとしましょう:
{
_id:1,
Name: “Sepp Maier”,
Country: “Germany”
}
次の方法で、[名前]フィールドを降順のインデックスにすることができます。
db.collection.createIndex({Name: -1})
このメソッドは、まだ存在していない場合に限り、同じ仕様のインデックスを作成します。
MongoDBのインデックスの種類
MongoDBにはさまざまなタイプのデータが含まれるため、これらのデータタイプとクエリをサポートするためにさまざまなタイプのインデックスが派生します。
-
単一フィールド
ドキュメントの単一のフィールドを使用すると、上記の例のように、フィールドを昇順または降順でインデックスにすることができます。さらに、埋め込みドキュメント全体にインデックスを作成できます。例:
{ _id: “xyz”, Contact:{ email: “[email protected]”, phone:”+420 78342823” }, Name: “Sergio” }
連絡先フィールドは埋め込みドキュメントであるため、次のコマンドを使用して昇順のインデックスにすることができます:
db.collection.createIndex({ Contact: 1})
クエリでは、次のようにドキュメントをフェッチできます:
db.collection.find({ Contact: {email: “[email protected]”, phone:”+420 78342823”} })
ベストプラクティスは、特に大量のデータが含まれる場合にバックグラウンドでインデックスを作成することです。これは、アプリケーションがインデックスの作成中にデータにアクセスする必要があるためです。
-
複合インデックス
複合インデックスは、クエリ内の並べ替え操作を容易にし、複数のフィールドで一致するクエリをサポートするためによく使用されます。複合インデックスを作成するための構文は次のとおりです。
db.collection.createIndex( { <field0>: <type>, <field1>: <type1>, ... } )
以下のサンプルデータの複合インデックスを作成する
{ _id: “1”, Name: “Tom”, Age: 24, Score:”80” } db.collection.createIndex({ Age: 1, Score:-1})
考慮事項:
- サポートできるフィールドは32フィールドのみです。
- フィールドの値は、インデックスのタイプを定義します。つまり、1は昇順で、-1は降順です。
- ハッシュインデックスタイプの複合インデックスを作成しないでください。
- 複合インデックスにリストされているフィールドの順序は重要です。並べ替えは、フィールドの順序に従って行われます。
-
マルチキーインデックス
ある時点で、配列コンテンツが格納されたフィールドがある場合があります。これらのフィールドにインデックスを付けると、要素ごとに個別のインデックスエントリが作成されます。したがって、配列の1つまたは複数の要素を照合することにより、配列で構成されるドキュメントをクエリで選択するのに役立ちます。これはMongoDBによって自動的に行われるため、マルチキータイプを明示的に指定する必要はありません。バージョン3.4以降、MongoDBは、どのインデックス付きフィールドがインデックスをマルチキーインデックスにするかを追跡します。この追跡により、データベースクエリエンジンはより厳密なインデックス境界を使用できるようになります。
マルチキーインデックスの制限
- コレクション内のドキュメントのマルチキーインデックスで使用できる配列フィールドは1つだけです。つまり
マルチキーインデックスを作成することはできません{ _id: 1, nums: [ 1, 2 ], scores: [ 30, 60 ]}
{ nums: 1, scores: 1 }
- マルチキーインデックスがすでに存在する場合、この制限に違反するドキュメントを挿入することはできません。つまり、
複合マルチキーインデックスを作成した後、numsフィールドとscoresフィールドの両方が配列であるドキュメントを挿入しようとすると、データベースは挿入に失敗します。{ _id: 1, nums: 1, scores: [ 30, 60 ]} { _id: 1, nums: [ 1, 2 ], scores: 30}
- コレクション内のドキュメントのマルチキーインデックスで使用できる配列フィールドは1つだけです。つまり
-
テキストインデックス
テキストインデックスは、コレクション内の文字列の検索クエリを改善するためによく使用されます。言語固有のストップワード(つまり、「the」、「a」、「or」)は保存されません。コレクションには、最大で1つのテキストインデックスを含めることができます。テキストインデックスを作成するには:
db.collection.createIndex({Name:”text”})
複数のフィールドにインデックスを付けることもできます。つまり
db.collection.createIndex({ Name:”text”, place:”text” })
複合インデックスには、昇順/降順のインデックスキーと組み合わせてテキストインデックスキーを含めることができますが、次のようになります。
- 複合テキストインデックスを作成するときは、すべてのテキストインデックスキーがインデックス仕様ドキュメント内で隣接している必要があります。
- 複合テキストインデックスには、マルチキーインデックスフィールドなどの他の特別なインデックスタイプを含めることはできません。
- $ text検索を実行するには、クエリ述語に先行するキーの等価一致条件が含まれている必要があります。
-
ハッシュインデックス
シャーディングは、水平スケーリングを改善するためにMongoDBで使用される手法の1つです。シャーディングには、ハッシュインデックスを使用したハッシュベースの概念が含まれることがよくあります。範囲に沿った値のよりランダムな分布は、これらのインデックスによって表されますが、同等性の一致のみをサポートし、範囲ベースのクエリをサポートすることはできません。
インデックスの全体的な運用上の考慮事項
- 各インデックスには、少なくとも8kBのデータスペースが必要です。
- アクティブな場合、各インデックスはディスクスペースとメモリを消費します。これは、キャパシティプランニングで追跡する場合に重要です。
- 読み取りと書き込みの比率が高いコレクションの場合、インデックスを追加するとパフォーマンスが向上し、インデックスのない読み取り操作には影響しません。
インデックスの使用に関する制限
- インデックスを追加すると、書き込み操作、特に書き込みと読み取りの比率が高いコレクションのパフォーマンスに悪影響があります。インデックスは、挿入ごとにインデックスも更新する必要があるという点でコストがかかります。
- 既存のドキュメントのインデックスエントリがインデックスキーの制限を超えた場合、MongoDBはインデックスを作成、更新、またはインデックス付きコレクションに挿入しません。
- 既存のシャードコレクションの場合、インデックスキーの制限を超えるインデックスエントリを持つインデックス付きフィールドを含むドキュメントがチャンクにあると、チャンクの移行は失敗します。
結論
MongoDBのパフォーマンスを向上させる方法はたくさんあり、インデックス作成もその1つです。インデックス作成は、スキャンする必要のあるドキュメントの数をなんらかの方法で最小限に抑えることで、データを取得するまでの待ち時間を短縮することで、クエリ操作を容易にします。ただし、特定のタイプのインデックスを使用することを決定する前に、いくつかの考慮事項を考慮する必要があります。読み取りと書き込みの比率が高いコレクションは、書き込みと読み取りの操作が高いコレクションよりもインデックスをより適切に利用する傾向があります。