MongoDB インデックス
インデックスはクエリのパフォーマンスを大幅に向上させます。インデックスがない場合、MongoDBはデータを読み取る際にコレクション内のすべてのドキュメントをスキャンし、クエリ条件に一致するレコードを選択する必要があります。この全コレクションスキャンは非常に非効率で、大量のデータを処理する際にはクエリに数十秒から数分かかることもあり、ウェブサイトのパフォーマンスに致命的な影響を与えます。インデックスは特殊なデータ構造で、データコレクション内で容易に走査できる形式で保存され、データベーステーブルの1つまたは複数の列の値を並べ替えるための構造です。
createIndex() メソッド
MongoDBは createIndex() メソッドを使用してインデックスを作成します。3.0.0バージョン以前では ensureIndex() メソッドが使用されていましたが、以降のバージョンでは createIndex() メソッドが使用されています。ensureIndex() はまだ使用可能ですが、createIndex() のエイリアスとして機能します。
構文
createIndex()メソッドの基本的な構文は以下の通りです:
>db.collection.createIndex(keys, options)
#バックグラウンドでインデックスを作成:
db.VideoTone.createIndex({"relatedCopyright.copyrightId" :1}, {background:true} ,{ name: "relatedCopyright.copyrightId"});
{background:true} はインデックスの後に、nameの前に配置する必要があります
構文の Key 値は作成するインデックスのフィールドで、1 は昇順インデックスの指定、降順インデックスを作成する場合は -1 を指定します。
例
1. titleフィールドに昇順インデックスを作成
>db.col.createIndex({"title":1})
2. 複合インデックス
createIndex() メソッドでは複数のフィールドを使用してインデックスを作成することもできます(リレーショナルデータベースでは複合インデックスと呼ばれます)。
>db.col.createIndex({"title":1,"description":-1})
#インデックス名を指定した複合インデックス:
gkdb_center_price.bpm_mq_message.createIndex({"bpmId":"1","dr":"1"},{"name":"idx_bpmId_dr"})
createIndex() はオプションパラメータも受け取ります。オプションパラメータは以下の通りです:
| パラメータ | 型 | 説明 |
|---|---|---|
| background | Boolean | インデックス作成プロセスは他のデータベース操作をブロックします。backgroundを指定すると、バックグラウンドでインデックスを作成できます。 "background" のデフォルト値は**false**です。 |
| unique | Boolean | 作成するインデックスが一意かどうかを指定します。trueを指定すると一意インデックスを作成します。デフォルト値は**false**です。 |
| name | string | インデックスの名前。指定しない場合、MongoDBはインデックスのフィールド名と並べ替え順序を結合してインデックス名を生成します。 |
| dropDups | Boolean | **3.0+バージョンでは廃止されました。**一意インデックスを作成する際に重複レコードを削除するかどうかを指定します。trueを指定すると一意インデックスを作成します。デフォルト値は**false**です。 |
| sparse | Boolean | ドキュメントに存在しないフィールドデータに対してインデックスを有効にしません。このパラメータは注意が必要で、trueに設定すると、インデックスフィールドに対応するフィールドを含まないドキュメントはインデックス内で検索されません。デフォルト値は**false**です。 |
| expireAfterSeconds | integer | 秒単位の数値を指定してTTLを設定し、コレクションの生存時間を設定します。 |
| v | index version | インデックスのバージョン番号。デフォルトのインデックスバージョンはmongodがインデックスを作成した際に実行されていたバージョンに依存します。 |
| weights | document | インデックスの重み値。1から99,999の間の数値で、他のインデックスフィールドに対するスコアの重みを示します。 |
| default_language | string | td>テキストインデックスの場合、このパラメータはストップワードおよびステミングとトークナイザーのルールのリストを決定します。デフォルトは英語です。|
| language_override | string | テキストインデックスの場合、このパラメータはドキュメント内に含まれるフィールド名を指定し、言語がデフォルトのlanguageを上書きします。デフォルト値はlanguageです。 |
例
バックグラウンドでインデックスを作成:
db.values.createIndex({open: 1, close: 1}, {background: true})
バックグラウンドオプション background:true を追加することで、インデックス作成をバックグラウンドで実行できます。
コレクションにインデックスがあるか確認:
db.Audit.getIndexes();
クエリの実行計画を確認:
db.FileExchangeTask.find({name:1}).explain()
mongoでインデックスを追加:
db.collection.createIndex({"列名":1});
1、コレクションのインデックスを確認
db.col.getIndexes()
2、コレクションのインデックスサイズを確認
db.col.totalIndexSize()
3、コレクションのすべてのインデックスを削除
db.col.dropIndexes()
4、コレクションの指定インデックスを削除
db.col.dropIndex("インデックス名")
5、単一インデックスを作成:
db.col.createIndex({"title":1})
6、複合インデックスを作成:
db.col.createIndex({"title":1,"description":-1})
7、バックグラウンドでインデックスを作成(インデックス作成プロセスは他のデータベース操作をブロックしますが、backgroundを指定するとバックグラウンドでインデックスを作成できます)
db.values.createIndex({open: 1, close: 1}, {background: true})
8、バックグラウンドで一意インデックスを作成:
db.values.createIndex({open: 1, close: 1}, {background: true,unique: true})
MongoDB 高度なインデックス
以下のドキュメントコレクション(users)を考えてみましょう:
{
"address": {
"city": "Los Angeles",
"state": "California",
"pincode": "123"
},
"tags": [
"music",
"cricket",
"blogs"
],
"name": "Tom Benzamin"
}
上記のドキュメントには address サブドキュメントと tags 配列が含まれています。
配列フィールドのインデックス
タグに基づいてユーザーを検索する場合、コレクション内の配列 tags にインデックスを付ける必要があります。配列内でインデックスを作成するには、配列内の各フィールドに個別にインデックスを付ける必要があります。したがって、配列 tags にインデックスを作成する際には、music、cricket、blogsの3つの値に対して個別のインデックスが作成されます。
配列インデックスを作成するには、以下のコマンドを使用します:
>db.users.ensureIndex({"tags":1})
インデックスを作成後、コレクションの tags フィールドを以下のように検索できます:
>db.users.find({tags:"cricket"})
インデックスが使用されていることを確認するには、explainコマンドを使用できます:
>db.users.find({tags:"cricket"}).explain()
上記コマンドの実行結果に "cursor" : "BtreeCursor tags_1" と表示されれば、インデックスが使用されていることを示します。
サブドキュメントフィールドのインデックス
city、state、pincodeフィールドでドキュメントを検索する必要がある場合、これらのフィールドはサブドキュメントのフィールドであるため、サブドキュメントにインデックスを付ける必要があります。
サブドキュメントの3つのフィールドにインデックスを作成するコマンドは以下の通りです:
>db.users.ensureIndex({"address.city":1,"address.state":1,"address.pincode":1})
インデックスを作成後、サブドキュメントのフィールドを使用してデータを検索できます:
>db.users.find({"address.city":"Los Angeles"})
クエリ式は指定されたインデックスの順序に従う必要はありません。MongoDBが自動的に最適化します。したがって、上記で作成したインデックスは以下のクエリをサポートします:
>db.users.find({"address.state":"California","address.city":"Los Angeles"})
以下のクエリも同様にサポートされます:
>db.users.find({"address.city":"Los Angeles","address.state":"California","address.pincode":"123"})
MongoDB インデックスの制限
追加のオーバーヘッド
各インデックスは一定のストレージスペースを占有し、挿入、更新、削除操作の際にもインデックスを操作する必要があります。したがって、コレクションに対する読み取り操作がほとんどない場合、インデックスを使用しないことをお勧めします。
メモリ(RAM)使用
インデックスはメモリ(RAM)に保存されるため、インデックスのサイズがメモリの制限を超えないことを確認する必要があります。インデックスのサイズがメモリの制限を超える場合、MongoDBは一部のインデックスを削除し、パフォーマンスが低下します。
クエリ制限
以下のクエリではインデックスを使用できません:
- 正規表現および非演算子、$nin、$notなど
- 算術演算子、$modなど
- $where句
したがって、ステートメントがインデックスを使用しているかどうかを確認し、explainを使用して確認することが良い習慣です。
インデックスキー制限
2.6バージョンから、既存のインデックスフィールドの値がインデックスキーの制限を超える場合、MongoDBはインデックスを作成しません。
ドキュメントの挿入がインデックスキー制限を超える
ドキュメントのインデックスフィールドの値がインデックスキーの制限を超える場合、MongoDBはドキュメントをインデックスコレクションに変換しません。mongorestoreおよびmongoimportツールと同様です。
最大範囲
- コレクション内のインデックスは64個まで
- インデックス名の長さは128文字まで
- 複合インデックスは最大31個のフィールドを持つことができます