带有1B文档的MongoDB,最优化的过滤器返回最近更新的文档

时间:2014-08-01 13:01:54

标签: mongodb sharding

我在一个集合中有一个超过1B文档的生产mongo数据库,它跨越多个服务器在_id上分片。我正在尝试将此集合中最近更新的记录复制到Red Shift。

分片键:

db.sample_collection.ensureIndex({_ id:“hashed”})

sh.shardCollection(“sample_collection.sample_object”,{_ id:“hashed”})

示例'sample_object'文档

{
    "_id" : ObjectId("527a6c9226d6b7770ab05345"),
    "p": ISODate("2013-10-27T14:30:18.000Z"),
    "a" : {
        "ln" : "Doe",
        "id" : NumberLong(3),
        "fn" : "John",
    },
    "co" : {
        "ct" : 2,
        "it" : [
                {'t': 'loreum', 'u' : NumberLong(300), 'd': ISODate("2013-10-28T14:30:18.000Z")},
                {'t': 'loreum', 'u' : NumberLong(400), 'd': ISODate("2013-10-29T14:30:18.000Z")},
                ..]
    },
    "li" : {
        "ct" : 2,
        "it" : [
                {'u' : NumberLong(500), 'd': ISODate("2013-10-30T14:30:18.000Z")},
                {'u' : NumberLong(501), 'd': ISODate("2013-10-29T14:30:18.000Z")},
                ..]
    },

}

选项#1:

我正在分析这些数据,我需要查询一段时间内“更新”的文档。 即,我想返回所有已经过p(已发布)的对象或者在“2014-07-01”和“2014-07-03”之间添加的li.it(item)或co.it(item)。< / p>

这样做最有效的方法是什么?

选项#2:

我正在评估的另一个选项是我是否要添加一个带有更新日期的'u'属性来说明文档何时更新 (即,li或co项目已添加)

如果我对流程进行了更改以确保新文档具有此属性,我将如何遍历现有文档并追溯添加此文档?

过滤'u'会比选项1更高效吗?我正在将此选项视为使用来自mongoexport的COPY FROM JSON

1 个答案:

答案 0 :(得分:1)

选项#1(多个日期)

对此进行索引并不是一个很好的选择,因为看起来您理想情况下需要一个包含p(日期)和两个日期数组(lt.it和{{1}的复合索引}})。复合索引最多只能包含one array field。即使您可以这样做,根据建议的日期数量,索引也会非常大,查询将涉及检查多个字段以推断上次更新日期。

选项#2(单个更新日期)

添加索引co.it(最新更新日期)绝对是一种更好的方法,可以进行简单且高效的查询。

  

如果我对流程进行了更改以确保新文档具有此属性,我将如何遍历现有文档并追溯添加此文档?

您可以使用$exists operator查找尚未设置此字段的文档。

警告散列碎片键

详细说明Neil的评论:散列的分片键为您提供了良好的写入分发,代价是能够进行范围查询(所有查询都变为分散 - 聚集)。如果您的常见查询是基于日期的范围(并且您关注性能),那么您可能chose a more appropriate shard key支持这些查询。但是,由于分片键是immutable,并且您想查询&#34;更新&#34;日期,它听起来不像是更改分片键有助于你的用例。