Regex MongoDB中带有正则表达式过滤器的Count()查询:性能缓慢

Regex MongoDB中带有正则表达式过滤器的Count()查询:性能缓慢,regex,performance,mongodb,Regex,Performance,Mongodb,使用MongoDB 2.6.5 我有一个具有这种结构的文档集合: { "_id" : ObjectId("5485cd0c6b0f96004220e414"), "exampleList" : [{ "Value" : "uri:obj:id:1258477.479.129403280" },{ "Value" : "uri:obj:id:1258477.542.542541247" }, { "Value" : "uri:obj:id

使用MongoDB 2.6.5

我有一个具有这种结构的文档集合:

{
  "_id" : ObjectId("5485cd0c6b0f96004220e414"),
  "exampleList" : [{
      "Value" : "uri:obj:id:1258477.479.129403280"
    },{
      "Value" : "uri:obj:id:1258477.542.542541247"
    }, {
      "Value" : "uri:obj:id:1258477.365.455255425"
    }
    [...]
    {
      "Value" : "uri:obj:id:1258477.147.855556255"
    }]
}
我在“exampleList.Value”上设置了一个多键索引

我想用类型为“starts with”的正则表达式请求它,但根据正则表达式,它可能非常慢。正则表达式的固定部分越短(结果越多),处理速度越慢

1亿文档集“myCollection”的演示:

最快执行(立即):

快速执行(几秒钟):

执行速度较慢(几秒钟):

执行速度慢(约2分钟)

非常非常慢的执行(未终止,几分钟)


我不明白为什么所有这些查询中的处理时间都不一样。

第一个正则表达式完成得很快,因为它只使用显式字符

/^uri:obj:id:1258477\.479\.129403280$/
与使用贪婪通配符“*”的其他正则表达式进行比较

/^uri:obj:id:1258477\.47.*$/
它在字符串的开头包含最短的一组确定字符,在数百万个文档中,可能有许多与第一部分匹配


尝试将“.*”替换为绝对长度或范围,即“.{0,25}”。如果可用,用string.beginsWith方法替换可能会更快。

MongoDB必须在更改正则表达式时逐渐扫描更多文档(例如,查询引擎可以根据索引和正则表达式排除更少的文档)。尝试使用
explain
,我打赌
nscanned
会增加。我已经使用explain做了测试,你是对的。我理解你说的,但我有一个问题:为什么MongoDB需要扫描文档以获得count()查询?指标不够;我正在寻找一种有效的方法,在我的多键索引中执行“start with”查询。也许你有解决办法吗?“*”和“.”之间没有明显的区别。治疗时间中的{0,25}。也许可以尝试将25的长度减少到更适合您的数据的长度,您期望的最大长度是多少?使用“{0,10}”进行测试,但这并不是更好
> db.myCollection.count({"exampleList.Value":{$regex:/^uri:obj:id:1258477\.479\.1.*$/}})
40947
> db.myCollection.count({"exampleList.Value":{$regex:/^uri:obj:id:1258477\.479.*$/}})
342275
> db.myCollection.count({"exampleList.Value":{$regex:/^uri:obj:id:1258477\.47.*$/}})
/^uri:obj:id:1258477\.479\.129403280$/
/^uri:obj:id:1258477\.47.*$/