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
选项指定了不同的压缩算法。例如,要将新天气集合的压缩算法更改为 snappydb.createCollection( "weather", { timeseries: { timeField: "timestamp" }, storageEngine: { wiredTiger: { configString: "block_compressor=snappy" } } } )
4 限制
- 不支持的功能
不支持如下功能:
-
聚合操作
$out
and$merge
不能使用聚合管道$out
和$merge
操作, 从另一个集合输出或合并到时间序列集合。 -
更新和删除
从 MongoDB 5.0.5版本开始,可以对时间序列集合执行一些删除和更新操作。-
更新命令必须满足以下要求:
- 查询可能只匹配 metaField 字段值
- update 命令只能修改 metaField 字段值
- 必须使用仅包含更新运算符表达式的更新文档执行更新
- update 命令可能不会限制要更新的文档的数量。必须使用带有 multi: true 或 updateMany() 方法的更新命令。
- 他更新命令不能设置 upsert: true的更新插入操作
-
删除命令必须满足以下要求
- 查询可能只匹配 metaField 字段值
- 删除命令可能不会限制要删除的文档数量,使用带有 justOne: false 或 deleteMany() 方法的删除命令。
要自动删除旧数据,可以设置自动删除 (TTL)时间。 要从集合中删除所有文档,可以使用 drop() 方法删除集合。
-
-
集合容量
测量文档的最大大小为 4 MB -
集合修改
集合的类型只能在创建集合时设置。
现有集合无法转换为时间序列集合。 同时也无法将时间序列集合转换为不同的集合类型。 -
timeseries 参数修改
-
timeField
和metaField
参数只能在创建集合时设置,不能在创建后修改 - 一旦设置了
granularity
参数,一次只能增加一个级别,从"seconds"到“minutes”或从“minutes”到“hours”。不允许进行其他更改。如果您需要将粒度从“seconds”更改为“hours”,请先将粒度增加到“minutes”,然后再增加到“hours”
-
-
固定集合 (capped collection)
不能将时间序列集合创建为固定集合 -
二级索引(secondary index)
可以在指定为timeField
和metaField
的字段上添加二级索引。如果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 秒时间间隔之后,过期数据可能会存在一段时间。
网友评论