使用正则表达式,MongoDB发现速度很慢

时间:2013-07-12 12:54:34

标签: mongodb

我目前开发的系统使用MongoDB 2.4.4

我有一组用户。

有一个综合索引:{ "LASTNAME" : 1 , "FIRSTNAME" : 1 , "EMAIL" : 1 , "CITY" : 1 , "STATUS" : 1} 我也尝试使用单个索引,但没有提高性能

系统包含400,000条测试记录。

查询(来自org.springframework.data.mongodb.core.query.Query的Java调试):

{ "LASTNAME" : { "$regex" : "^Schm"}},
  Fields: { "FIRSTNAME" : 1 , "EMAIL" : 1 , "CITY" : 1 , "STATUS" : 1 ,"LASTNAME" : 1},
  Sort: { "LASTNAME" : 1 , "FIRSTNAME" : 1 , "EMAIL" : 1 , "CITY" : 1 , "STATUS" : 1}

在16ms内完成。真是太棒了。

此查询未显示在MongoDB控制台中(此处没有要发布的调试信息)。

但是,我不仅喜欢搜索,而且还应该不区分大小写。

查询:

{ "LASTNAME" : { "$regex" : "^Schm" , "$options" : "i"}},
  Fields: { "FIRSTNAME" : 1 , "EMAIL" : 1 , "CITY" : 1 , "STATUS" : 1 , "LASTNAME" : 1},
  Sort: { "LASTNAME" : 1 , "FIRSTNAME" : 1 , "EMAIL" : 1 , "CITY" : 1 , "STATUS" : 1}

在897毫秒内执行。这是不可接受的缓慢。

Mongo控制台显示:

query: { query: { LASTNAME: /^Schm/i },
  orderby: { LASTNAME: 1, FIRSTNAME: 1, EMAIL: 1, CITY:1, STATUS: 1 }
} cursorid:1252405545564528 ntoreturn:25 ntoskip:0 nscanned:297651
keyUpdates:0 numYields: 1 locks(micros) r:1391715 nreturned:25 reslen:4422 897ms

有人可以看到。这不是指向索引问题的scanAndOrder问题。

然后我尝试以适合大多数情况的下一个方式解决它(从用户插入,小写和大写),但这也慢。 我的期望是,只要第一次查询它就会执行三次。

查询:

{ "$or" : [ { "LASTNAME" : { "$regex" : "^Schm"}} , { "LASTNAME" : { "$regex" : "^schm"}} , { "LASTNAME" : { "$regex" : "^SCHM"}}]},
  Fields: { "FIRSTNAME" : 1 , "EMAIL" : 1 , "CITY" : 1 , "STATUS" : 1 , "LASTNAME" : 1},
  Sort: { "LASTNAME" : 1 , "FIRSTNAME" : 1 , "EMAIL" : 1 , "CITY" : 1 , "STATUS" : 1}

在1300毫秒内执行。没什么好说的。

MongoDB控制台:

query: { query: { $or: [ { LASTNAME: /^Schm/ }, { LASTNAME: /^schm/ }, { LASTNAME: /^SCHM/ } ] },
  orderby: { LASTNAME: 1, FIRSTNAME: 1, EMAIL: 1, CITY: 1, STATUS: 1 }
} cursorid:43560166842085 ntoreturn:25 ntoskip:0 nscanned:297651
keyUpdates:0 numYields: 1 locks(micros) r:1531168 nreturned:25 reslen:4422 1300ms

那么,我怎样才能搜索几乎没有第一次搜索速度的不区分大小写? 最大150ms!

1 个答案:

答案 0 :(得分:7)

只要添加不区分大小写,就不能再使用索引了。在构建需要支持搜索的应用程序时,这是一个重要的设计问题。

为了解决这个问题,你应该将一个已经小写的姓氏版本存储在另一个字段中,然后对这种情况进行敏感查询(显然将所有搜索查询翻译成小写,然后再传递给Mongo)。

修改

看起来在2.4中添加了文本搜索。阅读它here,看看它是否能满足您的需求。

作为旁注,如果你真的关心性能(从你的问题判断,听起来你可能是这样),你应该重新考虑搜索你的数据存储引擎。考虑使用其他搜索引擎,例如ElasticSearch(或简单的Lucene索引),以保持搜索流量不受主数据存储的影响。