我目前开发的系统使用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!
答案 0 :(得分:7)
只要添加不区分大小写,就不能再使用索引了。在构建需要支持搜索的应用程序时,这是一个重要的设计问题。
为了解决这个问题,你应该将一个已经小写的姓氏版本存储在另一个字段中,然后对这种情况进行敏感查询(显然将所有搜索查询翻译成小写,然后再传递给Mongo)。
修改强>
看起来在2.4中添加了文本搜索。阅读它here,看看它是否能满足您的需求。
作为旁注,如果你真的关心性能(从你的问题判断,听起来你可能是这样),你应该重新考虑搜索你的数据存储引擎。考虑使用其他搜索引擎,例如ElasticSearch(或简单的Lucene索引),以保持搜索流量不受主数据存储的影响。