MongoDB単一フィールドインデックスと複合インデックス
MongoDBでよく見られるインデックスには、単一フィールドインデックスと複合インデックスがある.
単一フィールド索引
インデックスのないクエリー
インデックスの作成
今回はusernameにインデックスを新規作成し、1はインクリメンタル配列を示します.
インデックス解析
注意事項
新しいインデックスを作成すると、ドキュメントを更新(挿入、更新、削除)するたびにインデックスが更新されます.MongoDBは、各集合に最大64個のインデックスしかないことを制限する.通常、1つの特定の集合において、2つ以上のインデックスを持つべきではない.通常、インデックスは、一般的なクエリーのフィールドに作成するべきであり、一般的でないフィールドに対してインデックスを作成するべきではない.
複合インデックス
インデックスに対応する値は一定の順序で配列するため、インデックスを用いる文書の並べ替えが非常に速い.しかし、ソートを行う場合は、1つのインデックスしか使用できません.使用するインデックスを最初の位置に置く必要があります.以下の例では、集合中のデータ量が比較的大きいため、直接並べ替えは、MongoDBの1回の操作に対するメモリ制限32 Mを超える.従って、以下の操作で用いるusers集合データ量は10 Wである.
上記の例ではageをソートしてからusernameをソートする.usernameにインデックスを作成しましたが、このクエリはusernameインデックスには使用できません.explain情報のクエリー
メモリが98 Kを使用していることを発見し、すべての10 Wのドキュメントをスキャンし、124 msを費やした.
複合インデックスの作成
このクエリが比較的一般的である場合、複合インデックス(compound index)と呼ばれる2つのフィールドにインデックスを一緒に作成することができる.このインデックスは、クエリに複数のソートがある場合や、クエリ条件に複数のキーがある場合に便利です.
コンポジットインデックス解析
3つ目は新しく追加した複合インデックスであることがわかる.上記のクエリとexplain情報を再度行う.1000個のドキュメントを返し、1000個のドキュメントをスキャンするだけで、1 msかかります.以前のインデックスが使用されていなかった場合、すべてのドキュメントをスキャンし、124 msかかりました.
結論
単純なインデックスでも複合インデックスでも.正しく使用する場合、クエリーの速度が大幅に速くなります.
ステートメント
コレクションサイズ
インデックスの状況
時間がかかる
スキャンドキュメント数
db.users.find({username:”user0115”})
1M
なし
318ms
1M
db.users.find({username:”user0115”})
1M
db.users.ensureIndex({“username”:1})
0ms
1
db.users10W.find().sort({“age”: 1 , “username” : 1}).limit(1000)
0.1M
なし
124ms
0.1M
db.users10W.find().sort({“age”: 1 , “username” : 1}).limit(1000)
0.1M
db.users10W.ensureIndex({“age”:1,”username”:1})
1ms
1000
要点:索引の問合せ:
db.users10W.getIndexes()
インデックスの作成:
単純インデックス:db.users.ensureIndex(「username」:1})複合インデックス:db.users10W.ensureIndex({“age”: 1,”username”: 1})
索引の削除
db.users10W.dropIndex(“username_1”)
単一フィールド索引
インデックスのないクエリー
>db.users.find({username:"user0115"}).explain(true)
// , docsExamined 100W, , executionTimeMillis 318ms
//db.users.find({username:"user123456"}).explain(true).executionStats.executionTimeMillis
"executionStats" : {
.....
"executionSuccess" : true,
"executionTimeMillis" : 318,
"nReturned" : 1,
"totalDocsExamined" : 1000000,
"totalKeysExamined" : 0
.....
}
インデックスの作成
今回はusernameにインデックスを新規作成し、1はインクリメンタル配列を示します.
>db.users.ensureIndex({"username":1})
インデックス解析
db.users.find({username:"user0115"}).explain(true)
// , indexName , executionTimeMillis 0ms,totalDocsExamined 1, 1 ,
....
"indexName" : "username_1",
"indexVersion" : 1,
"invalidates" : 0,
"isEOF" : 1,
"isMultiKey" : false,
"isPartial" : false,
"isSparse" : false,
"isUnique" : false,
"keyPattern" : {
"username" : 1
}
......
"executionSuccess" : true,
"executionTimeMillis" : 0,
"nReturned" : 1,
"totalDocsExamined" : 1,
"totalKeysExamined" : 1
.....
注意事項
新しいインデックスを作成すると、ドキュメントを更新(挿入、更新、削除)するたびにインデックスが更新されます.MongoDBは、各集合に最大64個のインデックスしかないことを制限する.通常、1つの特定の集合において、2つ以上のインデックスを持つべきではない.通常、インデックスは、一般的なクエリーのフィールドに作成するべきであり、一般的でないフィールドに対してインデックスを作成するべきではない.
複合インデックス
インデックスに対応する値は一定の順序で配列するため、インデックスを用いる文書の並べ替えが非常に速い.しかし、ソートを行う場合は、1つのインデックスしか使用できません.使用するインデックスを最初の位置に置く必要があります.以下の例では、集合中のデータ量が比較的大きいため、直接並べ替えは、MongoDBの1回の操作に対するメモリ制限32 Mを超える.従って、以下の操作で用いるusers集合データ量は10 Wである.
>db.users10W.find().sort({"age": 1 , "username" : 1}).limit(1000)
上記の例ではageをソートしてからusernameをソートする.usernameにインデックスを作成しましたが、このクエリはusernameインデックスには使用できません.explain情報のクエリー
.....
"memLimit" : 33554432,
"memUsage" : 98341,
.....
"executionSuccess" : true,
"executionTimeMillis" : 124,
"nReturned" : 1000,
"totalDocsExamined" : 100000,
"totalKeysExamined" : 0
.....
メモリが98 Kを使用していることを発見し、すべての10 Wのドキュメントをスキャンし、124 msを費やした.
複合インデックスの作成
このクエリが比較的一般的である場合、複合インデックス(compound index)と呼ばれる2つのフィールドにインデックスを一緒に作成することができる.このインデックスは、クエリに複数のソートがある場合や、クエリ条件に複数のキーがある場合に便利です.
>db.users10W.ensureIndex({"age":1,"username":1})
>db.users10W.getIndexes()
{
"key" : {
"_id" : NumberInt("1")
},
"name" : "_id_",
"ns" : "test.users10W",
"v" : NumberInt("1")
},
{
"key" : {
"username" : 1
},
"name" : "username_1",
"ns" : "test.users10W",
"v" : NumberInt("1")
},
{
"key" : {
"age" : 1,
"username" : 1
},
"name" : "age_1_username_1",
"ns" : "test.users10W",
"v" : NumberInt("1")
}
コンポジットインデックス解析
3つ目は新しく追加した複合インデックスであることがわかる.上記のクエリとexplain情報を再度行う.1000個のドキュメントを返し、1000個のドキュメントをスキャンするだけで、1 msかかります.以前のインデックスが使用されていなかった場合、すべてのドキュメントをスキャンし、124 msかかりました.
...
"executionSuccess" : true,
"executionTimeMillis" : 1,
"nReturned" : 1000,
"totalDocsExamined" : 1000,
"totalKeysExamined" : 1000
.....
"indexName" : "age_1_username_1",
"indexVersion" : 1,
"isMultiKey" : false,
"isPartial" : false,
"isSparse" : false,
"isUnique" : false,
"keyPattern" : {
"age" : 1,
"username" : 1
},
....
結論
単純なインデックスでも複合インデックスでも.正しく使用する場合、クエリーの速度が大幅に速くなります.
ステートメント
コレクションサイズ
インデックスの状況
時間がかかる
スキャンドキュメント数
db.users.find({username:”user0115”})
1M
なし
318ms
1M
db.users.find({username:”user0115”})
1M
db.users.ensureIndex({“username”:1})
0ms
1
db.users10W.find().sort({“age”: 1 , “username” : 1}).limit(1000)
0.1M
なし
124ms
0.1M
db.users10W.find().sort({“age”: 1 , “username” : 1}).limit(1000)
0.1M
db.users10W.ensureIndex({“age”:1,”username”:1})
1ms
1000
要点:索引の問合せ:
db.users10W.getIndexes()
インデックスの作成:
単純インデックス:db.users.ensureIndex(「username」:1})複合インデックス:db.users10W.ensureIndex({“age”: 1,”username”: 1})
索引の削除
db.users10W.dropIndex(“username_1”)