mongodb - 时间序列集合(time series collection)

1. 介绍

在mongodb 5.0 版本新增的功能,它有效地存储了一段时期内的测量序列。时间序列数据是随着时间收集的任何类型的数据,并由一个或多个不变参数唯一标识, 这些不变参数通常又称为是数据源的元数据
示例:

示例 时间序列数据 元数据
天气 温度 传感器标识,地理位置
股票 股票价格 股票行情、交易所
网站访问者 访问数量 网站地址

与普通集合相比,将时序数据存储在时序集合中提高了查询效率,减少了时序数据和次级索引(secondary index)的磁盘存储空间。

2. 操作指令

  • 创建
    db.createCollection( <name>,
     {
       timeseries: {                  // Added in MongoDB 5.0
          timeField: <string>,        // required for time series collections
          metaField: <string>,
          granularity: <string>
       },
      expireAfterSeconds: <number>,
     }
    )
    
    参数名 类型 含义
    timeseries.timeField string 必选参数。每个时间序列文档中包含日期的字段的名称。时间序列集合中的文档必须具有有效的 BSON 日期作为 timeField 的值
    timeseries.metaField string 可选参数,每个时间序列文档中包含元数据的字段的名称。指定字段中的元数据应该是用于标记一系列唯一文档的数据。元数据应该很少(如果有的话)改变。 指定字段的名称不可以是 _id 或与 timeseries.timeField 相同。元数据的字段可以是任何数据类型
    timeseries.granularity string 可选参数,可选值为"second","minute","hours",默认值是"seconds"。手动设置granularity参数以通过优化时间序列集合中的数据在内部存储的方式来提高性能。选择与连续传入测量之间的时间跨度最接近的granularity参数值来匹配。如果指定了 timeseries.metaField,则要考虑连续的传入的测量值 和指定的metaField字段具有相同唯一值的时间跨度。如果测量值来自同一来源,则它们通常具有相同的唯一值。如果未指定 timeseries.metaField,请考虑插入集合中的所有测量值之间的时间跨度
    expireAfterSeconds number 可选参数 ,通过指定文档过期的秒数来启用时间序列集合中文档的自动删除
    示例:
      db.weather.insertMany( [
     {
        "metadata": { "sensorId": 5578, "type": "temperature" },
        "timestamp": ISODate("2021-05-18T00:00:00.000Z"),
        "temp": 12
     },
     {
        "metadata": { "sensorId": 5578, "type": "temperature" },
        "timestamp": ISODate("2021-05-18T04:00:00.000Z"),
        "temp": 11
     },
     {
        "metadata": { "sensorId": 5578, "type": "temperature" },
        "timestamp": ISODate("2021-05-18T08:00:00.000Z"),
        "temp": 11
     },
     {
        "metadata": { "sensorId": 5578, "type": "temperature" },
        "timestamp": ISODate("2021-05-18T12:00:00.000Z"),
        "temp": 12
     },
     {
        "metadata": { "sensorId": 5578, "type": "temperature" },
        "timestamp": ISODate("2021-05-18T16:00:00.000Z"),
        "temp": 16
     },
     {
        "metadata": { "sensorId": 5578, "type": "temperature" },
        "timestamp": ISODate("2021-05-18T20:00:00.000Z"),
        "temp": 15
     }, {
        "metadata": { "sensorId": 5578, "type": "temperature" },
        "timestamp": ISODate("2021-05-19T00:00:00.000Z"),
        "temp": 13
     },
     {
        "metadata": { "sensorId": 5578, "type": "temperature" },
        "timestamp": ISODate("2021-05-19T04:00:00.000Z"),
        "temp": 12
     },
     {
        "metadata": { "sensorId": 5578, "type": "temperature" },
        "timestamp": ISODate("2021-05-19T08:00:00.000Z"),
        "temp": 11
     },
     {
        "metadata": { "sensorId": 5578, "type": "temperature" },
        "timestamp": ISODate("2021-05-19T12:00:00.000Z"),
        "temp": 12
     },
     {
        "metadata": { "sensorId": 5578, "type": "temperature" },
        "timestamp": ISODate("2021-05-19T16:00:00.000Z"),
        "temp": 17
     },
     {
        "metadata": { "sensorId": 5578, "type": "temperature" },
        "timestamp": ISODate("2021-05-19T20:00:00.000Z"),
        "temp": 12
     }
    ] )
    
  • 查询
    示例
    db.weather.findOne({
     "timestamp": ISODate("2021-05-18T00:00:00.000Z")
    })
    

3 特性

时间序列集合的特性类似于普通集合。您可以像往常一样插入和查询数据。 MongoDB 将时间序列集合视为内部集合的可写非物化视图,在插入时自动将时间序列数据组织成优化的存储格式。 当您查询时间序列集合时,您每次测量操作一个文档。对时间序列集合的查询利用优化的内部存储格式并更快地返回结果。

  • 索引
    时间序列集合的实现使用内部集合来减少磁盘使用和提高查询效率。时间序列集合自动按时间排序和索引数据。 listIndexes方法 不会显示时间序列集合的内部索引

  • 默认压缩算法
    时间序列集合默认的压缩算法是zstd, 而忽略全局默认压缩算法 (snappy)。除非在创建集合时使用 storageEngine 选项指定了不同的压缩算法。例如,要将新天气集合的压缩算法更改为 snappy

    db.createCollection(
    "weather",
    {
       timeseries: {
          timeField: "timestamp"
       },
       storageEngine: {
          wiredTiger: {
             configString: "block_compressor=snappy"
          }
       }
      }
    )
    

4 限制

  • 不支持的功能
    不支持如下功能:
  1. Client-side field level encryption
  2. reIndex
  3. Change streams
  4. Database Triggers
  5. GraphQL API
  6. Atlas Search
  7. Realm Sync
  8. Data API
  9. Schema validation rules
  • 聚合操作 $out and $merge
    不能使用聚合管道 $out$merge操作, 从另一个集合输出或合并到时间序列集合。

  • 更新和删除
    从 MongoDB 5.0.5版本开始,可以对时间序列集合执行一些删除和更新操作。

    1. 更新命令必须满足以下要求:

      • 查询可能只匹配 metaField 字段值
      • update 命令只能修改 metaField 字段值
      • 必须使用仅包含更新运算符表达式的更新文档执行更新
      • update 命令可能不会限制要更新的文档的数量。必须使用带有 multi: true 或 updateMany() 方法的更新命令。
      • 他更新命令不能设置 upsert: true的更新插入操作
    2. 删除命令必须满足以下要求

    • 查询可能只匹配 metaField 字段值
    • 删除命令可能不会限制要删除的文档数量,使用带有 justOne: false 或 deleteMany() 方法的删除命令。

    要自动删除旧数据,可以设置自动删除 (TTL)时间。 要从集合中删除所有文档,可以使用 drop() 方法删除集合。

  • 集合容量
    测量文档的最大大小为 4 MB

  • 集合修改
    集合的类型只能在创建集合时设置。
    现有集合无法转换为时间序列集合。 同时也无法将时间序列集合转换为不同的集合类型。

  • timeseries 参数修改

    1. timeFieldmetaField 参数只能在创建集合时设置,不能在创建后修改
    2. 一旦设置了granularity参数,一次只能增加一个级别,从"seconds"到“minutes”或从“minutes”到“hours”。不允许进行其他更改。如果您需要将粒度从“seconds”更改为“hours”,请先将粒度增加到“minutes”,然后再增加到“hours”
  • 固定集合 (capped collection)
    不能将时间序列集合创建为固定集合

  • 二级索引(secondary index)
    可以在指定为 timeFieldmetaField 的字段上添加二级索引。如果 metaField 字段的字段值是一个文档,还可以在该文档内的字段上创建二级索引。
    metaField 不支持以下几种索引类型: 2d, 2dsphere,text
    二级索引不支持以下索引属性:TTL,unique, partial

  • 分片
    从 MongoDB 5.0.6版本开始,支持分片时间序列集合。使用分片时序集合时,不能修改分片时序集合的granularity参数。

  • 事务
    事务中不能包括时间序列集合写操作, 但是可以包括读操作

5. TTL(Set up Automatic Removal )

创建时间序列集合时,可以使用 expireAfterSeconds 参数设置自动删除过期的文档:

// 示例
db.createCollection(
  "weather24h",
  {
     timeseries: {
        timeField: "timestamp",
        metaField: "metadata",
        granularity: "hours"
     },
     expireAfterSeconds: 86400
  }
)

过期阈值是 timeField 字段值加上设定的过期秒数
例如 weather24h集合中有如下的文档

{
   "metadata": {"sensorId": 5578, "type": "temperature"},
   "timestamp": ISODate("2021-05-18T10:00:00.000Z"),
   "temp": 12
}

那该文档将在ISODate("2021-05-18T10:00:00.000Z") + 86400s 的时间过期

  • 过期文档删除时机
    MongoDB 不保证过期数据会在过期后立即被删除。一旦存储桶中的所有文档都过期,删除过期存储桶的后台任务会在下次运行期间删除该存储桶。单个桶允许覆盖的最大时间跨度由时间序列集合的 granularity参数决定:

    删除过期存储桶的后台任务每 60 秒运行一次。因此,在文档过期、桶中所有其他文档过期和后台任务运行期间,文档可能会保留在集合中。 由于删除操作的持续时间取决于 mongod 实例的工作负载,因此在后台任务运行之间的 60 秒时间间隔之后,过期数据可能会存在一段时间。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,657评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,662评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,143评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,732评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,837评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,036评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,126评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,868评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,315评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,641评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,773评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,859评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,584评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,676评论 2 351

推荐阅读更多精彩内容