MongoDBのcount()が遅い!ensureIndex()で高速化する回避策を徹底解説
MongoDBのcount()が遅くなる原因と対策
MongoDBでcount()メソッドを実行すると、条件に一致するドキュメントを探すためにコレクション全体をスキャンする場合があり、データ量が増えると処理速度が著しく低下します。この問題を回避するには、ensureIndex()を使ってあらかじめインデックスを作成しておくのが効果的です。インデックスを利用することで、count()のパフォーマンスを大幅に向上させることができます。
なお、MongoDB 3.0以降ではensureIndex()は非推奨となり、代わりにcreateIndex()の使用が推奨されています。両者は同じ役割を持つため、本記事の手順はどちらのメソッドでも同様に適用できます。
サンプルコレクションの作成
まず、動作を確認するためにドキュメントを含むコレクションを作成します。以下のクエリを実行して、学生情報のドキュメントを複数件挿入しましょう。
> db.countPerformanceDemo.insertOne({"StudentName":"John","StudentCountryName":"US"});
{
"acknowledged" : true,
"insertedId" : ObjectId("5c8ebcf82f684a30fbdfd55f")
}
> db.countPerformanceDemo.insertOne({"StudentName":"Mike","StudentCountryName":"UK"});
{
"acknowledged" : true,
"insertedId" : ObjectId("5c8ebd042f684a30fbdfd560")
}
> db.countPerformanceDemo.insertOne({"StudentName":"David","StudentCountryName":"AUS"});
{
"acknowledged" : true,
"insertedId" : ObjectId("5c8ebd112f684a30fbdfd561")
}
> db.countPerformanceDemo.insertOne({"StudentName":"Carol","StudentCountryName":"US"});
{
"acknowledged" : true,
"insertedId" : ObjectId("5c8ebd1a2f684a30fbdfd562")
}
> db.countPerformanceDemo.insertOne({"StudentName":"Bob","StudentCountryName":"UK"});
{
"acknowledged" : true,
"insertedId" : ObjectId("5c8ebd212f684a30fbdfd563")
}
> db.countPerformanceDemo.insertOne({"StudentName":"David","StudentCountryName":"UK"});
{
"acknowledged" : true,
"insertedId" : ObjectId("5c8ebd9a2f684a30fbdfd564")
}
> db.countPerformanceDemo.insertOne({"StudentName":"David","StudentCountryName":"US"});
{
"acknowledged" : true,
"insertedId" : ObjectId("5c8ebd9e2f684a30fbdfd565")
}登録したドキュメントの確認
find()メソッドを使うと、コレクション内のすべてのドキュメントを表示できます。以下のクエリを実行してみましょう。
> db.countPerformanceDemo.find().pretty();
実行結果は次のとおりです。
{
"_id" : ObjectId("5c8ebcf82f684a30fbdfd55f"),
"StudentName" : "John",
"StudentCountryName" : "US"
}
{
"_id" : ObjectId("5c8ebd042f684a30fbdfd560"),
"StudentName" : "Mike",
"StudentCountryName" : "UK"
}
{
"_id" : ObjectId("5c8ebd112f684a30fbdfd561"),
"StudentName" : "David",
"StudentCountryName" : "AUS"
}
{
"_id" : ObjectId("5c8ebd1a2f684a30fbdfd562"),
"StudentName" : "Carol",
"StudentCountryName" : "US"
}
{
"_id" : ObjectId("5c8ebd212f684a30fbdfd563"),
"StudentName" : "Bob",
"StudentCountryName" : "UK"
}
{
"_id" : ObjectId("5c8ebd9a2f684a30fbdfd564"),
"StudentName" : "David",
"StudentCountryName" : "UK"
}
{
"_id" : ObjectId("5c8ebd9e2f684a30fbdfd565"),
"StudentName" : "David",
"StudentCountryName" : "US"
}ensureIndex()でインデックスを作成する
続いて、count()を高速化するためのインデックスを作成します。ensureIndex()に対象フィールドを指定して実行します。
> db.countPerformanceDemo.ensureIndex({"StudentName":1});
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}実行結果を見ると、インデックス数が「numIndexesBefore: 1」から「numIndexesAfter: 2」に増えており、StudentNameフィールドへのインデックスが正常に作成されたことがわかります。
インデックス作成後にcount()を実行する
インデックスの作成が完了したら、count()メソッドを実行します。ここでは、StudentNameが「David」と一致するレコードの件数をカウントしています。
> db.countPerformanceDemo.find({"StudentName":"David"}).count();実行結果は次のとおりです。
3
「David」という名前の学生は3人いるため、正しく「3」が返されました。このように、検索対象のフィールドにインデックスを設定しておくことで、count()はコレクション全体をスキャンすることなくインデックスを参照して結果を返せるようになり、大規模なコレクションでも高速に動作します。
まとめ
MongoDBのcount()が遅い場合は、頻繁に検索・集計に使うフィールドに対してensureIndex()(またはcreateIndex())でインデックスを作成するのが有効な対策です。特に本番環境で大量のドキュメントを扱う場合には、クエリの実行計画をexplain()で確認しながら、適切なインデックス設計を行うことをおすすめします。
-
MongoDBの$push演算子を使って配列に要素を追加する方法
MongoDBの$push演算子とはMongoDBの$push演算子は、ドキュメント内の配列フィールドに対して新しい要素を追加するための更新演算子です。既存の配列の末尾に値を追加できるため、リスト形式のデータを扱う際に非常に便利です。この記事では、実際のコード例を通して、$push演算子の基本的な使い方を解説します。1. コレクションとドキュメントを作成するまず、insertOne()メソッドを使用して、コレクションにドキュメントを挿入します。ここでは「Subjects」という配列フィールドを持つ2つのドキュメントを作成します。> db.demo738.insertOne({Subjec
-
MySQLのCOUNT(DISTINCT)処理が遅い原因と、インデックスを使った高速化の方法
MySQLのCOUNT(DISTINCT)を高速化するにはインデックスが有効MySQLでCOUNT(DISTINCT)を実行した際に処理が遅くなる場合は、対象カラムにINDEX(インデックス)を作成することで大幅に高速化できます。ここでは、複合インデックスを設定したテーブルを作成し、実際にCOUNT(DISTINCT)クエリを実行する手順を解説します。1. インデックス付きテーブルを作成するまず、FirstNameとLastNameの2つのカラムに複合インデックスを設定したテーブルを作成します。mysql> create table DemoTable1905 ( Fir