2013-04-20 111 views
2

当输入数据是单个值并且收集数据包含最小/最大范围时,在Mongo中查找数据的最有效方式是什么?例如:在mongo中搜索范围

record = { min: number, max: number, payload } 

需要查找记录中的最小/最大范围内的数字。范围从不相交。关于范围的大小没有可预测性。

集合中有~6M条记录。如果我解压缩范围(每个值都有范围记录),我会查看约4B记录。

我创建的{min:1,max:1}复合索引,但尝试使用搜索:

db.block.find({min:{$lte:value},max:{$gte:value}) 

...时间介于几到几十秒钟。以下是explain()getIndexes()的输出。有什么技巧可以使搜索执行速度显着加快?

NJmongo:PRIMARY> db.block.getIndexes() 
[ 
    { 
      "v" : 1, 
      "key" : { 
        "_id" : 1 
      }, 
      "ns" : "mispot.block", 
      "name" : "_id_" 
    }, 
    { 
      "v" : 1, 
      "key" : { 
        "min" : 1, 
        "max" : 1 
      }, 
      "ns" : "mispot.block", 
      "name" : "min_1_max_1" 
    } 
] 


NJmongo:PRIMARY> db.block.find({max:{$gte:1135194602},min:{$lte:1135194602}}).explain() 
{ 
    "cursor" : "BtreeCursor min_1_max_1", 
    "isMultiKey" : false, 
    "n" : 1, 
    "nscannedObjects" : 1, 
    "nscanned" : 1199049, 
    "nscannedObjectsAllPlans" : 1199050, 
    "nscannedAllPlans" : 2398098, 
    "scanAndOrder" : false, 
    "indexOnly" : false, 
    "nYields" : 7534, 
    "nChunkSkips" : 0, 
    "millis" : 5060, 
    "indexBounds" : { 
      "min" : [ 
        [ 
          -1.7976931348623157e+308, 
          1135194602 
        ] 
      ], 
      "max" : [ 
        [ 
          1135194602, 
          1.7976931348623157e+308 
        ] 
      ] 
    }, 
    "server" : "ccc:27017" 
} 
+0

这很长时间 - 你有多少RAM?这是什么版本的MongoDB?你可以在查询运行时运行mongostat并捕获它的输出吗? – 2013-04-20 03:33:20

+0

@AsyaKamsky就像Leopd所说的那样,它并不是真的意外,数据库必须搜索大量记录(查看解释输出)。除非MongoDB支持几何索引,否则这只是生活中的事实,或者我必须使用一些技巧(现在评估他):) – 2013-04-20 08:24:21

+0

它确实支持2d索引,但它们的语义含义是专门针对地理位置的。如果你想出一些聪明的应用程序,它仍然可能适用于你。 – Leopd 2013-04-20 16:33:20

回答

1

如果您block记录的范围从来没有重叠,那么你就可以做到这一点与更快:

db.block.find({min:{$lte:value}}).sort({min:-1}).limit(1) 

这个查询将返回几乎是瞬间,因为它可以找到记录与简单的查找中该指数。

您正在运行的查询速度很慢,因为两个子句分别匹配数百万个必须合并的记录。事实上,我认为您的查询在minmax上的单独索引运行速度更快(可能快得多),因为您的复合索引的max部分只能用于给定的min - 不搜索具有特定max的文档。

+0

这正是我正在寻找的。我需要添加的唯一东西 - 是如果找到元素(如范围中有空洞),则检查'max'的值。谢谢! – 2013-04-20 08:36:58

+0

不同之处在于,您对查询速度缓慢的原因不正确 - 没有两个子句返回将被合并的数百万个子句。问题在于,索引的主要部分使用的不平等性不足以提供选择性。 – 2013-04-21 06:17:02

+0

@Asya同意最大的问题是'max'上没有可用的索引,所以它必须扫描集合。但我认为,为了这个策略,真正高效的mongo将不得不支持目前还没有的索引交叉:https://jira.mongodb.org/browse/SERVER-3071 – Leopd 2013-04-22 16:08:49