【发布时间】:2013-07-11 00:36:03
【问题描述】:
我目前开发的系统,使用的是 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}
在 16 毫秒内执行。太棒了。
此查询未显示在 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
那么,我怎样才能搜索不区分大小写,几乎有第一次搜索的速度呢? 最长 150 毫秒!
【问题讨论】:
-
附带说明,我删除了 Java 标记,因为这个问题只与 Mongo 相关,与 Java 无关
-
您能否为您的
$or查询发布explain() -
我不知道如何,使用 Spring MongoTemplate。目前正在考虑切换到 mongo-java-driver...
-
你会从 mongo 控制台而不是 Spring 获得
explain() -
我现在直接在2.4.5版本的mongo shell上测试了。排序操作让它变得如此缓慢(没有在 16 毫秒内对 or 语句进行排序):-> pastebin.com/Gd0LRPb7
标签: mongodb