0

我目前开发的系统使用 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 毫秒!

4

1 回答 1

9

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

为了克服这个问题,您应该将已经小写的姓氏版本存储在另一个字段中,并区分大小写查询(显然在将所有搜索查询传递给 Mongo 之前将它们转换为小写)。

编辑

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

作为旁注,如果您真的关心性能(根据您的问题判断,听起来您可能是这样),您应该重新考虑搜索您的数据存储引擎。考虑一个替代搜索引擎,例如 ElasticSearch(或简单的 Lucene 索引),以使搜索流量远离您的主数据存储。

于 2013-07-12T12:57:21.457 回答