【问题标题】:MongoDB, how to create index for query containing a geospatial query, a range query and sort on different columns?MongoDB,如何为包含地理空间查询、范围查询和不同列排序的查询创建索引?
【发布时间】:2012-02-23 20:44:30
【问题描述】:

因此,如果我有一个执行以下操作的查询(在伪代码中)

find(a 附近的 x, b > y).sort(c)

其中a是geo列,b是long类型,c也是long类型

(a:2d, b:1, c:1) 上的复合索引是否有效并建议?

【问题讨论】:

    标签: mongodb indexing geospatial compound-index


    【解决方案1】:

    地理空间查询有自己的索引类别(正如您所提到的),并且地理哈希极大地提高了第一次键查找的索引性能——如果您可以正确设置它,它比范围更好。无论如何,我认为您的策略会奏效:关键是将 $maxDistance 设置为相当小的值。

    我插入了 1000 万条随机地理记录来匹配您的描述,如下所示:

    { "_id" : ObjectId("4f28e1cffc90631d239f8b5a"), "a" : [ 46, 47 ], "b" : ISODate("2012-02-01T06:53:25.543Z"), "c" : 19 }
    { "_id" : ObjectId("4f28e1bdfc90631d239c4272"), "a" : [ 54, 48 ], "b" : ISODate("2012-02-01T06:53:32.699Z"), "c" : 20 }
    { "_id" : ObjectId("4f28e206fc90631d23aac59d"), "a" : [ 46, 52 ], "b" : ISODate("2012-02-01T06:55:14.103Z"), "c" : 22 }
    { "_id" : ObjectId("4f28e1a7fc90631d23995700"), "a" : [ 54, 52 ], "b" : ISODate("2012-02-01T06:52:33.312Z"), "c" : 27 }
    { "_id" : ObjectId("4f28e1d7fc90631d23a0e9e7"), "a" : [ 52, 46 ], "b" : ISODate("2012-02-01T06:53:11.315Z"), "c" : 31 }
    

    当 maxDistance 低于 10 时,性能非常好。

    db.test13.find({a:{$near:[50,50], $maxDistance:4}, b:{$gt:d}}).sort({c:1}).explain();
    {
    "cursor" : "GeoSearchCursor",
    "nscanned" : 100,
    "nscannedObjects" : 100,
    "n" : 100,
    "scanAndOrder" : true,
    "millis" : 25,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "isMultiKey" : false,
    "indexOnly" : false,
    "indexBounds" : {
    
    }
    }
    

    如果你忽略 maxDistance,它会开始受到相当大的影响。一些查询最多需要 60 秒才能运行。次要范围参数似乎没有多大帮助,即使范围相当窄 - 它似乎都是关于 maxDistance。

    我建议您尝试一下以了解地理空间索引的性能。这是我的测试插入循环。您也可以尝试限制位数以降低分辨率

    function getRandomTime() {
       return new Date(new Date() - Math.floor(Math.random()*1000000));
    }
    
    function getRandomGeo() {
       return [Math.floor(Math.random()*360-180),Math.floor(Math.random()*360-180)];
    }
    
    function initialInsert() {
       for(var i = 0; i < 10000000; i++) {
          db.test13.save({
             a:getRandomGeo(),
             b:getRandomTime(),
             c:Math.floor(Math.random()*1000)
          });
       }
    }
    

    【讨论】:

    • mongodb.org/display/DOCS/Indexing+Advice+and+FAQ 中提到的内容让我感到困扰 3. 仅对一列使用范围查询或排序,是否有任何 cmets?
    • 拉出其中一个范围查询会快得多。你真的需要这样查询吗?
    • 是的,我需要在给定距离(列 a:2d,并假设 $near 是一个范围查询)和给定时间(列 b:1)内查找实体,然后对另一列 c:1。有没有更好的方法来达到同样的效果?
    • 如果你把它设为 a="something" 或 b="something",它会很快。
    • 嗯。我会尝试一下——$near 在其中使用了一些地理哈希,因此它的行为可能不会太糟糕。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-07
    • 2011-08-21
    • 2015-01-10
    • 2017-01-25
    • 1970-01-01
    • 2019-09-23
    • 2023-03-16
    相关资源
    最近更新 更多