Sparse Indexes
スパース インデックスには、インデックス フィールドに null 値が含まれていても、インデックスフィールドを持つドキュメントのエントリのみが含まれます。インデックスは、インデックス付きフィールドが欠落しているドキュメントをスキップします。コレクションのすべてのドキュメントが含まれているわけではないため、インデックスは "スパース" です。一方、非スパース インデックスにはコレクション内のすべてのドキュメントが含まれ、インデックス フィールドを含まないドキュメントには null 値がストアされます。
重要
MongoDB には、 の部分インデックスを作成するオプションが用意されています。 部分インデックスは 、スパースインデックスの機能のスーパーセットを提供します。 部分インデックスは、スパースインデックスよりも優先され、
スパース インデックスの作成
スパース インデックスを作成するには、sparse
オプションを true
に設定した db.collection.createIndex()
メソッドを使用します。
たとえば、 mongosh
の次の操作では、addresses
コレクションの xmpp_id
フィールドにsparse indexが作成されます。
db.addresses.createIndex( { "xmpp_id": 1 }, { sparse: true } )
インデックスは、xmpp_id
フィールドを含まないドキュメントをインデックスしません。
注意
MongoDB のスパース インデックスと、他のデータベースのブロックレベル インデックスを混同しないでください。特定のフィルターを備えた密なインデックスと考えてください。
動作
スパース インデックスと不完全な結果
スパース インデックスによって、クエリやソート操作の結果セットが不完全になる場合、hint()
で明示的にインデックスを指定しない限り、MongoDB はそのインデックスを使用しません。
たとえば、クエリ { x: { $exists: false } }
では、明示的なヒントがない限り x
フィールドにスパース インデックスを使用しません。動作の詳細を示す例については、「コレクションのスパース インデックスが完全な結果を返さない」を参照してください。
コレクション内のすべてのドキュメントの count()
を実行するときに、スパース インデックスを指定する hint()
を含めると(つまり、クエリ述語が空の場合)、スパース インデックスの結果が不正確なカウントになった場合でも、スパース インデックスが使用されます。
db.collection.insertOne( { _id: 1, y: 1 } ); db.collection.createIndex( { x: 1 }, { sparse: true } ); db.collection.find().hint( { x: 1 } ).count();
正しいカウントを取得するには、コレクション内のすべてのドキュメントのカウントを実行するときに、スパース インデックスを使用して hint()
を実行しないでください。
db.collection.find().count(); db.collection.createIndex( { y: 1 } ); db.collection.find().hint( { y: 1 } ).count();
デフォルトでスパースなインデックス
次のインデックスの種類は、常にスパースです。
スパース複合インデックス
複合インデックスには、さまざまなタイプのスパースインデックスを含めることができます。インデックスのタイプの組み合わせによって、複合インデックスがドキュメントと一致する方法が決まります。
下表には、さまざまなタイプのスパースインデックスを含む複合インデックスの動作がまとめられています。
複合インデックスの構成要素 | 複合インデックスの動作 |
---|---|
Ascending indexes Descending indexes | 1 つ以上のキーの値を含むドキュメントのみ、インデックスが作成されます。 |
| |
|
スパースでユニークなプロパティ
インデックスがスパースかつ一意の場合、フィールドの値が重複するドキュメントがコレクションに含まれることはありませんが、キーが省略された複数のドキュメントは許可されます。
例
コレクションでのスパース インデックスの作成
以下のドキュメントを含むコレクション scores
を考慮します:
{ "_id" : ObjectId("523b6e32fb408eea0eec2647"), "userid" : "newbie" } { "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 } { "_id" : ObjectId("523b6e6ffb408eea0eec2649"), "userid" : "nina", "score" : 90 }
コレクションにはフィールド score
のスパース インデックスがあります:
db.scores.createIndex( { score: 1 } , { sparse: true } )
次に、scores
コレクションに対する次のクエリは、スパース インデックスを使用して、score
フィールドが($lt
)90
より小さいドキュメントを返します。
db.scores.find( { score: { $lt: 90 } } )
ユーザー ID "newbie"
のドキュメントには score
フィールドが含まれていないためにクエリ条件を満たさないことから、クエリではスパース インデックスを使用して結果を返すことができます。
{ "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 }
コレクションのスパース インデックスが完全な結果を返せない
以下のドキュメントを含むコレクション scores
を考慮します:
{ "_id" : ObjectId("523b6e32fb408eea0eec2647"), "userid" : "newbie" } { "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 } { "_id" : ObjectId("523b6e6ffb408eea0eec2649"), "userid" : "nina", "score" : 90 }
コレクションにはフィールド score
のスパース インデックスがあります:
db.scores.createIndex( { score: 1 } , { sparse: true } )
ユーザー ID "newbie"
のドキュメントには score
フィールドが含まれていないため、スパース インデックスにはそのドキュメントのエントリは含まれません。
scores
コレクションのすべてのドキュメントを score
フィールドでソートして返すには、次のクエリを考慮します:
db.scores.find().sort( { score: -1 } )
インデックス付きフィールドでソートしても、MongoDB は、完全な結果を返すことを目的としてクエリを満たすために、スパース インデックスを選択することはありません。
{ "_id" : ObjectId("523b6e6ffb408eea0eec2649"), "userid" : "nina", "score" : 90 } { "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 } { "_id" : ObjectId("523b6e32fb408eea0eec2647"), "userid" : "newbie" }
スパース インデックスを使用するには、hint()
を使用してインデックスを明示的に指定します。
db.scores.find().sort( { score: -1 } ).hint( { score: 1 } )
インデックスを使用すると、score
フィールドを持つドキュメントのみが返されます。
{ "_id" : ObjectId("523b6e6ffb408eea0eec2649"), "userid" : "nina", "score" : 90 } { "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 }
ユニーク制約を持つスパース インデックス
以下のドキュメントを含むコレクション scores
を考慮します:
{ "_id" : ObjectId("523b6e32fb408eea0eec2647"), "userid" : "newbie" } { "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 } { "_id" : ObjectId("523b6e6ffb408eea0eec2649"), "userid" : "nina", "score" : 90 }
次の操作を使用して、score
フィールドにユニーク制約とスパースフィルターを持つインデックスを作成できます。
db.scores.createIndex( { score: 1 } , { sparse: true, unique: true } )
このインデックスにより、score
フィールドにユニークな値を持つドキュメント、あるいは score
フィールドが含まれていないドキュメントの挿入が許可されます。そのため、scores
コレクション内の既存のドキュメントを前提として、インデックスでは以下の挿入操作が可能です。
db.scores.insertMany( [ { "userid": "newbie", "score": 43 }, { "userid": "abby", "score": 34 }, { "userid": "nina" } ] )
ただし、score
値が 82
と 90
のドキュメントがすでに存在するため、インデックスでは次のドキュメントの追加が許可されません。
db.scores.insertMany( [ { "userid": "newbie", "score": 82 }, { "userid": "abby", "score": 90 } ] )
ユニークスパース/非スパースインデックス
MongoDB5.0 以降、 キー パターン が同じ 一意のスパース および 一意の非スパース インデックスを単一コレクションに混在させることができます。
ユニークおよびスパースインデックスの作成
次の例では、キー パターンが同じで sparse
オプションが異なる複数のインデックスを作成します。
db.scoreHistory.createIndex( { score : 1 }, { name: "unique_index", unique: true } ) db.scoreHistory.createIndex( { score : 1 }, { name: "unique_sparse_index", unique: true, sparse: true } )
基本インデックスとスパースインデックスの作成
スパース オプションの有無にかかわらず、同じキー パターンで基本インデックスを作成することもできます。
db.scoreHistory.createIndex( { score : 1 }, { name: "sparse_index", sparse: true } ) db.scoreHistory.createIndex( { score : 1 }, { name: "basic_index" } )