聊聊 MongoDB 时期序列汇合

名词解释

bucket:带有相反的元数据且在一段有限度的间 隔区间内的测量值组。

bucket collection :用于存储时序型汇合的底层的分组桶的系统汇合。复制、分片和索引都是在桶级别上成功的。

measurement:带有特定时期序列的K-V汇合。

meta-data:时序序列里很少随时期变动的K-V对,同时可以用于识别整个时序序列。

time-series:一段距离内的一系列测量值。

time-series collection:一种示意可写的非物化的视图的汇合类型,它准许存储和查问多个时期序列,每个序列可以有不同的元数据。

MongoDB 在5.0中支持了新的timeseries collection类型的选项,该类型用于存储时序型数据。timeseriescollection提供了一组用于拔出和查问测量值的便捷接口,同时底层实践的数据是存储在以bucket方式的汇合中。

在创立timeseriescollection时,timeField字段是最小必备的性能项。metaField是另一个可选的、可被指定的元数据字段,它是用于在bucket中对测量值分组的依据。MongoDB经过提供expireAfterSeconds字段选项,也支持了对测量值的过时机制。

在mydb数据库中有个以mytscoll 命名的timeseriescollection,该汇合在MongoDB外部的catelog(用于存储汇合或视图的消息)里是由一个视图和一个系统汇合组成的。

该视图就是经过aggregation里的$_internalUnpackBucket来成功倒退bucket里数据的。

该视图是可写的(仅支持拔出)。同时每个被拔出的文档必定蕴含时期字段。

在查问视图时,它会隐式地倒退底层在bucket collection中存储的数据,而后前往原始的非bucket方式的文档数据。

每一个在bucket collection里的文档,都示意了一组区间距离的时序型数据。

假设在创立timeseriescollection时,定义了metaField元数据字段,那么一切在bucket里的测量值都会有这个通用的元数据字段。

除了时期范畴,bucket还限度了每个文档数据的总条数以及测量值的大小。

Bucket Collection Schema

_id Object ID with  component equal to control. fieldcontrol  Some statistics  the measurements such minmax  of>>version  Version of bucket schema. Currently fixed at  since this  the first iteration of series collections.min  field  of first measurement  this bucket rounded down based  granularityfield0 minimum value of  across all measurementsfield1 maximum value of  across all measurements...max  field  of last measurement  this bucketfield0 maximum value of  across all measurementsfield1 maximum value of  across all measurements...closed   Optional signals the>not receive any additional measurements.meta metadata field if specified at creation value common to all measurements  this bucketdata  field   of first measurement  of second measurement...  of nth measurementfield0  value of   first measurement value of   first measurement...field1  value of   first measurement value of   first measurement......

索引

为了保障timeseries collection的查问可以受益于索引扫描而不是全表扫描,timeseriescollection准许索引可以被创立在时期上,元数据上以及元数据的子属性上。从MongoDB5.2开局,在timeseriescollection也准许索引被创立在测量值上。用户经常使用createIndex命令提供的索引规范被转换为底层buckets collection的形式。

当索引被创立后,可以经过listIndexes命令或$indexStats聚合方案来审核。listIndexes和$indexStats是作用于timeseries collections的,口头时,它们会在外部将底层的bucketcollection的索引转化成timeseries格局的索引,并前往。比如,当咱们在元数据字段中定义有mm的timeseriescollection上口头listIndexes命令时,底层的bucket collection的{meta:1}索引,将会以{mm:1}格局前往。

dropIndex 和collMod (hidden: , expireAfterSeconds: ) 也雷同支持在timeseriescollection上。

时期字段上支持的索引类型:

元数据字段和元数据子字段支持的索引类型:

仅在v5.2及以上版本,测量值字段支持的索引类型:

`timeseries collections 上不支持的索引类型,包括 惟一索引以及文本索引。

桶目录

为了保障高效地桶(分组)操作,咱们在BucketCatalog里保养了一组开启的桶,你可以在bucket_catalog.h找到。在更高的级别,咱们尝试着把并发写程序的写操作分组兼并为可以一同提交地批处置,以缩小对底层文档的写次数。写程序会拔出它的输入批处置里的每一个文档到BucketCatalog,而后BucketCatalog会前往一个BucketCatalog::WriteBatch的处置器。一旦成功上方那些拔出操作后,写程序就会审核每个写批处置。假设没有其余的写程序曾经对批处置申明提交的权益,那么它会申明权益,并会提交它的批处置。否则,写程序将会稍后再提交处置。当它审核完一切的批处置,写程序将会期待其余的写程序提交每个剩下的批处置。

在外部,BucketCatalog保养一组对每个bucket文档的降级操作。当批处置被提交时,它会将这些拔出转换到成buckets的列格局,并确保任何control字段的降级(例如control.min 和control.max)。

当bucket文档在没有经过BucketCatalog的状况下被降级时,写程序就须要为有疑问的文档或命名空间去调用BucketCatalog::clear,这样它就可以降级它的外部形态,防止写入任何或许破坏bucket 格局的数据。这通常由OP观察者处置,但或许须要经过其余中央去调用。

bucket既可以经过手动设置选项control.closed 标识来封锁,也可以在许多场景下经过 BucketCatalog智能封锁。假设BucketCatalog经常使用了超出给定的阈值(可经过主机参数timeseriesIdleBucketExpiryMemoryUsageThreshold控制)的更多内存,此时它将会开局去封锁闲暇的bucket。假设bucket是开启的且它没有任何未处于期待中未提交的测量值时,那么它就会被视为闲暇的bucket。在上方这些场下BucketCatalog 也会封锁bucket:假设它领有超越最大阈值(timeseriesBucketMaxCount)的测量值数据的数量;假设它领有过大的数据量大小(timeseriesBucketMaxSize);又或许一个新的测量值数据能否是会造成bucket在其最旧的时期戳和最新的时期戳之间跨度比准许的距离更长的时期(硬编码为一小时)。假设传入的测量值在原理上与曾经抵达给定bucket的度量不兼容,该bucket将被封锁,同时可以经常使用numBucketsClosedDueToSchemaChange度量启动跟踪。

在第一次性提交给定bucket的写批处置时,就会生成新的完整的文档。后续的批处置提交中,咱们只口头降级操作,不再生成新的完整的文档(因此称为‘经典’降级),是间接创立DocDiff(“delta”或许v2的降级)。

粒度

timeseries collection的granularity选项在汇合创立的时刻,可以被设置成seconds,minutes或许hours。前期可经过colMod操作来修正这个选项从seconds到minutes或许从minutes到hours,除此之外的转化修正目前都是不支持的。该参数想要示意在已给定的时序型测量数据之间的粗略的时时期隔,同时也用于调理其余外部参数对分组的影响。

单个bucket被准许的最大时期跨度,是由granularity选项控制,关于seconds,最大的时期跨度被设置成1小时,关于minutes就是24小时,关于hours就是30天。

当经过BucketCatalog开启新的bucket时,_id里的时期戳就是同等于control.min.的值,该值是从第一个拔出bucket的测量数据中依据granularity选项来向下近似舍入而失掉的。关于seconds,它将向下舍入到最凑近的分钟,关于minutes,将向下舍入到最凑近的小时,关于hours,它将向下舍入到最凑近的日期。在闰秒和日历中的其余不规定状况下,这种舍入或许并不完美,并且通常经过对自纪元以来的秒数启动基本模运算来成功,假定每分钟60 秒,每小时 60 分钟,以及每天 24 小时。

降级和删除

timeseries collection 支持合乎以下限度的删除语句:

同时降级满足上方雷同的条件,另外遵照:

这些降级与删除的口头都会被转换成相对应的底层的bucket collection的降级或删除操作。特意是,关于查问和降级文档,咱们会经常使用真正的字段meta交流汇合的metaField。(参见 Bucket 汇合规范)

例如,关于一个经常使用 metaField:"tag"创立的timeseries汇合db.ts,思考一个对这个汇合的降级操作,其查问语句是{"tag.tag.a": "a"} ,同时降级文档语句是{$set: {"tag.tag.a": "A"}, $rename: {"tag.tag.b": "tag.tag.c"}}。这个降级操作在db.system.buckets.ts上会被转换成,查问语句是{"meta.tag.a": "a"},降级语句是 {$set: {"meta.tag.a":"A"}, $rename: {"meta.tag.b":"meta.tag.c"}}。而后这个转换后的降级语句就可以像个别的降级操作一样口头。上方这些转换流程也实用于删除操作。

参考文献

MongoDB Blog: Time Series> 关于作者:黄璜

目前到任于上海DerbySoft,重要从事基础架构中业务流程设计及研发的上班,往常上班中MongoDB经常使用的较多。

在优化自己外文的才干的同时,也宿愿为社区做出庞大的奉献。

您可能还会对下面的文章感兴趣: