MongoDBにおける複合インデックスの習得
このガイドでは、データベースのパフォーマンス最適化に不可欠な手法であるMongoDBの複合インデックスの詳細を掘り下げます。基本的な仕組みの理解から、その有効性の分析、一般的な問題のトラブルシューティングまで、あらゆる点を網羅します。
1. 複合インデックスの理解
MongoDBでは、複合インデックスは単一ドキュメント内の複数のフィールドにまたがるインデックスです。単一フィールドインデックスは単一フィールドのクエリのみを高速化しますが、複合インデックスは複数のフィールドを含むクエリの速度を劇的に向上させ、アプリケーションのパフォーマンスに大きな影響を与えます。インデックス内のフィールドの順序は重要です。MongoDBはこの順序を使用して、ドキュメントを効率的に検索します。
インデックスの先頭フィールドに一致するクエリは、最も大きな恩恵を受けます。クエリが先頭フィールドのみを使用する場合、インデックスはフィルタリングとソートの両方に完全に活用されます。ただし、クエリがインデックスを超えるフィールドを使用する場合、MongoDBはインデックスを部分的に利用する可能性があり、残りの条件についてはコレクションスキャンにフォールバックし、パフォーマンスの向上を無効にする可能性があります。
たとえば、category
、price
、name
フィールドを持つproducts
コレクションを考えてみましょう。{ "category": 1, "price": -1 }
の複合インデックスは、category
でフィルタリングし、次にprice
を降順でソートするクエリを最適化します。
2. 複合インデックスの作成
db.collection.createIndex()
メソッドを使用すると、複合インデックスの作成は簡単です。引数は、キーがフィールド名を表し、値がソート順序(1は昇順、-1は降順)を表すドキュメントです。
// カテゴリ(昇順)と価格(降順)に複合インデックスを作成します
db.products.createIndex( { category: 1, price: -1 } );
// 複数のフィールドに複合インデックスを作成し、ソート順序を多様化します
db.users.createIndex( { firstName: 1, lastName: -1, age: 1 } );
// uniqueとsparseオプションを追加します
db.products.createIndex( { category: 1, price: -1 }, { unique: true, sparse: true } );
unique: true
はインデックス付きフィールド全体の一意性を強制し、sparse: true
はインデックス付きフィールドがnullでないドキュメントのみをインデックス付けします。
3. 複合インデックスを使用したクエリ
MongoDBのクエリ最適化ツールは、クエリが先頭フィールドに一致し、ソート順序が一致する場合、自動的に複合インデックスを使用します。たとえば、次のクエリは{ "category": 1, "price": -1 }
インデックスから恩恵を受けます。
db.products.find( { category: "Electronics" } ).sort( { price: -1 } );
このクエリはcategory
(先頭インデックスフィールド)でフィルタリングし、price
(インデックスのソート順序と一致)でソートします。ただし、このクエリはそれほど恩恵を受けません。
db.products.find( { price: { $lt: 100 } } ).sort( { category: 1 } );
price
は先頭フィールドではなく、ソート順序はインデックスと一致しません。
4. インデックス使用状況の分析
インデックスの使用状況を分析するには、db.collection.find().explain()
を使用します。これにより、どのインデックスが使用されたか(または使用されなかったか)、実行時間など、クエリ実行計画に関する詳細な情報が提供されます。
db.products.find( { category: "Electronics" } ).sort( { price: -1 } ).explain();
“executionStats”セクションを確認します。インデックスが使用されている場合、インデックスキーの使用状況と検査されたドキュメントの数が表示されます。”COLLSCAN”は、インデックスの使用よりも効率の低い完全なコレクションスキャンを示します。
5. ベストプラクティスと最適化
慎重なインデックスの選択が不可欠です。インデックスが多すぎると書き込み操作が遅くなり、インデックスが少なすぎるとクエリが非効率になります。頻繁に使用されるクエリパターンを優先し、必要に応じてインデックスを段階的に追加します。インデックスの使用状況を定期的に監視し、アプリケーションのニーズに合わせて調整します。より簡単なインデックス管理には、MongoDB Compass GUIの使用を検討してください。
6. よくある質問
- 複合インデックスはいくつ作成する必要がありますか?最適な数は、アプリケーションのクエリパターンによって異なります。インデックスが多すぎないようにバランスをとる必要があります。
- クエリがインデックスに完全に一致しない場合はどうなりますか?MongoDBはインデックスの一部を使用する可能性がありますが、一致しない部分についてはコレクションスキャンに頼る可能性があります。
- 昇順/降順のフィールドが混在する複合インデックスを作成できますか?はい、順序は最適なパフォーマンスにとって重要です。
- 複合インデックスを削除するにはどうすればよいですか?インデックス名または仕様を指定して、
db.collection.dropIndex()
を使用します。
// 名前で削除します
db.products.dropIndex("category_1_price_-1");
// 仕様で削除します
db.products.dropIndex( { category: 1, price: -1 } );