3

I've been playing around with the MongoDB C# driver for the first time and I'm finding some strange results in performance. When I query a collection with 3 million records with ordering and .Take(1) the reponse is nearly instantanious (3ms.). But when I .Take(2) on the same query it takes up to 10 seconds. The right index is in place and it's a very simple collection with test data.

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 才能有效地使用索引。此外,同时 /^a/, /^a. / 和 /^a。$/ 匹配等效字符串,它们具有不同的性能特征。如果存在适当的索引,则所有这些表达式都使用索引;但是,/^a。/ 和 /^a。$/ 更慢。/^a/ 匹配前缀后可以停止扫描。

我怀疑如果您在查询中使用explain 命令,您会发现包含该SearchString字段的索引没有得到有效使用。

我相信Take(1)比 a 快的原因Take(2)可能是您的SearchString索引仅用于查询的排序部分,并且第一个匹配发生在 B-Tree walk 的早期。第二次出现可能会在 B-Tree 遍历中发生得更晚,导致更高nscan(服务器扫描以查找结果的文档数量)。

要解决此问题并能够使用索引,我建议使用关键字搜索方法;或者,如果您有 v2.4+,您可以尝试文本搜索功能。

于 2013-08-27T15:46:18.207 回答