前回はデータの読み込みのパフォーマンス測定を実施しました。今回はインデックスの作成を行い、読み込み性能の改善を行いたいと思います。

Introduction

前回は、結果も課程も散々でした。
環境は前回と同じです。

Explanation

インデックスの設定

Indexes with C# Driverによれば、

Indexes can support the efficient execution of queries. MongoDB automatically creates an index on the _id field upon the creation of a collection.

訳: インデックスは効率的なクエリの実行をサポートすることができます。MongoDBは自動的に _id フィールド上にコレクション作成時にインデックスを作成します。

と言っています。
既にインデックスが張られているといっています。
といっても、_idフィールドなので、これまでの検索には影響しないと思います。
追加で設定する場合は、

var keys = Builders.IndexKeys.Ascending().Ascending(); await collection.Indexes.CreateOneAsync(keys);

と、するようです。
というわけで、前回の3種のオブジェクトの No プロパティ に昇順のインデックスを設定してみます。
こんな感じです。

1
2
3
4
5
6
7
8
9
10
private static void SetSmallIndex(MongoClient mongoClient)
{
Console.WriteLine("SetSmallIndex");

var database = mongoClient.GetDatabase(DatabaseName);
var collection = database.GetCollection<SmallObjectData>(CollectionName);

var keys = Builders<SmallObjectData>.IndexKeys.Ascending("No");
collection.Indexes.CreateOne(keys);
}

インデックスの設定後

割と時間がかかりました。1,000,000件も登録されていればそうでしょう。

Index

mongo-expressで確認すると、Indexes # が 2 になっています。

そして、前回と同じように、検索を実行します。検索結果の個数は10になります。
その結果が下記になります。

オブジェクトサイズ/オブジェクト数 1,000,000 1,000,000 (インデックス適用後)
Small (51.0 bytes) 420.8 ms 610.8 ms
Middle (80.1 kb) 221577.1 ms 586 ms
Large (100 kb) 計測不可 588 ms

劇的に改善しました。370倍です。Largeに至っては計測できるようにさえなりました。
Smallが悪化してますが、誤差でしょう。多分。
実行後、mongod.exe のメモリ量は大きく増えていません。

検索結果の個数は影響するか?

前回、メモリ確保が原因なのか、途中で例外を投げて落ちました。
今回は、検索結果の個数が1,000,000から10になるようにしてあります。

では、これを変化させたら、検索速度はどう変化するでしょうか? 1,000,000件のデータを対象に、検索結果の個数が増えていった場合のパフォーマンスを下記に記載します。

オブジェクトサイズ/検索結果数 10 100 1,000 10,000 100,000
Small (51.0 bytes) 610.8 ms 515.6 ms 558.5 ms 582.8 ms 956.2 ms
Middle (80.1 kb) 586 ms 512 ms 1571.4 ms 7171.2 ms 計測不可
Large (100 kb) 588 ms 494.7 ms 1870.2 ms 11292.6 ms 計測不可

増えていくごとに悪化していく傾向です。
ただし、劇的に悪化しているのは、初回のクエリだけ100秒とかで、それ以降はキャッシュが聞いています。それでも、後半は 2,000 ms とかかかっていますが。
それでも、インデックスを設定する前と比べたら、劇的すぎる改善です。

Conclusion

バイナリファイルを扱う際は、必ずインデックスを設定し、検索のパフォーマンスを向上させるのと、検索途中の結果でOutOfMemoryExceptionを発生させないようにする必要があります。
必要なら複数のインデックスを設定して、結果が少なくなるようするべきです。

Source Code

テストに使った最終的なコードは下記になります。
https://github.com/takuya-takeuchi/Demo/tree/master/MongoDB7