Mongodb 在mongo中搜索范围

Mongodb 在mongo中搜索范围,mongodb,optimization,database,Mongodb,Optimization,Database,当输入数据为单个值且采集数据包含最小/最大范围时,在Mongo中查找数据的最有效方法是什么?例如: record = { min: number, max: number, payload } 需要找到一条记录,该记录的数字在该记录的最小/最大范围内。这些范围从不相交。范围的大小是不可预测的 该收藏中有约600万条记录。如果我解包范围(对范围中的每个值都有记录),我将看到大约4B条记录 我已经创建了{min:1,max:1}的复合索引,但尝试使用以下方法进行搜索: db.block.find(

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

record = { min: number, max: number, payload }
需要找到一条记录,该记录的数字在该记录的最小/最大范围内。这些范围从不相交。范围的大小是不可预测的

该收藏中有约600万条记录。如果我解包范围(对范围中的每个值都有记录),我将看到大约4B条记录

我已经创建了
{min:1,max:1}
的复合索引,但尝试使用以下方法进行搜索:

db.block.find({min:{$lte:value},max:{$gte:value})
。。。需要几秒到几十秒的时间。下面是
explain()
getindex()
的输出。有什么技巧可以让搜索执行得更快吗

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"
}

如果
记录的范围从不重叠,则可以通过以下方法更快地完成此任务:

db.block.find({min:{$lte:value}}).sort({min:-1}).limit(1)
这个查询几乎会立即返回,因为它可以通过在索引中进行简单的查找找到记录


您正在运行的查询速度很慢,因为这两个子句在数百万条必须合并的记录上都匹配。事实上,我认为如果在
min
max
上使用单独的索引,您的查询将运行得更快(可能更快),因为复合索引的
max
部分只能用于给定的
min
——而不是搜索具有特定
max

的文档,这是一段很长的时间——您有多少RAM?这是什么版本的MongoDB?您能在查询运行时运行mongostat并捕获其输出吗?@AsyaKamsky正如Leopd正确指出的,这并不是真的出人意料,数据库必须搜索大量记录(查看解释输出)。除非MongoDB支持几何索引,否则这只是生活中的事实,或者我必须使用一些技巧(现在评估他):)它确实支持2d索引,但它们的语义是专门针对geo的。不过,如果你能想出一些聪明的应用程序,它可能会对你有用。2d索引可以非常有效地用于重叠范围查询-它不必是实际坐标,只需开始、结束对(例如,在这种情况下,我需要1d索引:)使用线段(我可以重新利用2d,将第二坐标锁定为0)。然后我会调用geoNear()来查找距离我的点“最近”(距离为0)的线段@AsyaKamsky让我知道如果你想让我试试看,那正是我想要的。我唯一需要添加的是检查
max
的值,如果找到了元素(因为范围中有孔)。非常感谢。除了您对查询速度慢的原因不正确之外,没有两个返回数百万的子句将被合并。问题是索引的前导部分与一个不等式一起使用,该不等式没有提供太多的选择性。@Asya同意最大的问题是
max
上没有可用的索引,因此它必须扫描集合。但我认为,要使该策略真正有效,mongo必须支持索引交叉点,但它还没有: