3

初めて MongoDB C# ドライバーをいじってみましたが、パフォーマンスに奇妙な結果が見られます。順序付けと .Take(1) を使用して 300 万レコードのコレクションをクエリすると、応答はほぼ瞬時 (3 ミリ秒) になります。しかし、同じクエリで .Take(2) を実行すると、最大 10 秒かかります。適切なインデックスが配置されており、テスト データを含む非常に単純なコレクションです。

MongoClient client = new MongoClient();
MongoServer server = client.GetServer();

var database = server.GetDatabase("db_name");
var collection = database.GetCollection<MyType>("collection_name");

var query = from c in collection.AsQueryable<MyType>()
            where c.SearchString.Contains(searchString)
            orderby c.SearchString
            select c.SearchString;

List<string> results = query.Take(2).ToList();
4

1 に答える 1

4

MongoDB C# ドライバーは、string.Contains メソッドを正規表現に変換します。したがってc.SearchStringContains("abc")、次のように翻訳されます。

{ SearchString : /abc/ }

ただし、MongoDB は「で始まる」正規表現でのみインデックスを使用できます。ドキュメントからの引用:

$regex は、正規表現が文字列の先頭 (つまり ^) のアンカーを持ち、大文字と小文字を区別する一致である場合にのみ、インデックスを効率的に使用できます。さらに、while /^a/, /^a. /、および /^a。$/ は同等の文字列に一致しますが、パフォーマンス特性が異なります。適切なインデックスが存在する場合、これらの式はすべてインデックスを使用します。ただし、/^a. /、および /^a。$/ は遅いです。/^a/ は、プレフィックスの一致後にスキャンを停止できます。

クエリでExplain コマンドを使用すると、SearchStringフィールドを含むインデックスが効果的に使用されていないことがわかると思います。

Take(1)が a よりも高速である理由は、インデックスがクエリのソート部分にのみ使用され、最初の一致が B ツリー ウォークの非常に早い段階で発生するTake(2)可能性が高いためだと思います。SearchString2 番目の発生は、B ツリー ウォークのかなり後で発生する可能性が高く、その結果、はるかに多くなりnscanます (サーバーが結果を求めてスキャンするドキュメントの数)。

この問題を回避してインデックスを使用できるようにするには、キーワード検索アプローチのいずれかを使用することをお勧めします。または、v2.4+ を使用している場合は、テキスト検索機能を試すことができます。

于 2013-08-27T15:46:18.207 に答える