技術乾貨| MongoDB時間序列集合
名詞解釋
Glossary
bucket: 帶有相同的後設資料且在一段有限制的間 隔區間內的測量值組。
bucket collection : 用於儲存時序型集合的底層的分組桶的系統集合。複製、分片和索引都是在桶級別上完成的。
measurement: 帶有特定時間序列的K-V集合。
meta-data: 時序序列裡很少隨時間變化的K-V對,同時可以用於識別整個時序序列。
time-series: 一段間隔內的一系列測量值。
time-series collection: 一種表示可寫的非物化的檢視的集合型別,它允許儲存和查詢多個時間序列,每個序列可以有不同的後設資料。
MongoDB 在5.0中支援了新的
timeseries collection
型別的選項,該型別用於儲存時序型資料。
timeseries collection
提供了一組用於插入和查詢測量值的簡單介面,同時底層實際的資料是儲存在以
bucket
形式的集合中。
在建立
timeseries collection
時,
timeField
欄位是最小必備的配置項。
metaField
是另一個可選的、可被指定的後設資料欄位,它是用於在
bucket
中對測量值分組的依據。MongoDB通過提供
expireAfterSeconds
欄位選項,也支援了對測量值的過期機制。
在
mydb
資料庫中有個以
mytscoll
命名的
timeseries collection
,該集合在MongoDB內部的
catelog
(用於儲存集合或檢視的資訊)裡是由一個檢視和一個系統集合組成的。
-
mydb.mytscoll
是個檢視,它在MongoDB底層是用bucket collection
作為包含特定屬性的原始集合實現的: -
該檢視就是通過
aggregation
裡的$_internalUnpackBucket
來實現展開bucket
裡資料的。 -
該檢視是可寫的(僅支援插入)。同時每個被插入的文件必須包含時間欄位。
-
在查詢檢視時,它會隱式地展開底層在
bucket collection
中儲存的資料,然後返回原始的非bucket
形式的文件資料。 -
該系統集合的名稱空間是
mydb.system.buckets.mytscoll
,它是用來儲存實際資料的。 -
每一個在
bucket collection
裡的文件,都表示了一組區間間隔的時序型資料。 -
如果在建立
timeseries collection
時,定義了metaField
後設資料欄位,那麼所有在bucket
裡的測量值都會有這個通用的後設資料欄位。 -
除了時間範圍,
bucket
還限制了每個文件資料的總條數以及測量值的大小。
Bucket Collection Schema
{ _id: <Object ID with time component equal to control.min.<time field>>, control: { // <Some statistics on the measurements such min/max values of data fields> version: 1, // Version of bucket schema. Currently fixed at 1 since this is the // first iteration of time-series collections. min: { <time field>: <time of first measurement in this bucket, rounded down based on granularity>, <field0>: <minimum value of 'field0' across all measurements>, <field1>: <maximum value of 'field1' across all measurements>, ... }, max: { <time field>: <time of last measurement in this bucket>, <field0>: <maximum value of 'field0' across all measurements>, <field1>: <maximum value of 'field1' across all measurements>, ... }, closed: <bool> // Optional, signals the database that this document will not receive any // additional measurements. }, meta: <meta-data field (if specified at creation) value common to all measurements in this bucket>, data: { <time field>: { '0', <time of first measurement>, '1', <time of second measurement>, ... '<n-1>': <time of n-th measurement>, }, <field0>: { '0', <value of 'field0' in first measurement>, '1', <value of 'field0' in first measurement>, ... }, <field1>: { '0', <value of 'field1' in first measurement>, '1', <value of 'field1' in first measurement>, ... }, ... }}
索引
indexes
為了保證
timeseries collection
的查詢可以受益於索引掃描而不是全表掃描,
timeseries collection
允許索引可以被建立在時間上,後設資料上以及後設資料的子屬性上。從MongoDB5.2開始,在
timeseries collection
也允許索引被建立在測量值上。使用者使用
createIndex
命令提供的索引規範被轉換為底層
buckets collection
的模式。
-
timeseries collection
與底層的buckets collection
之間的索引對映轉換關係細節,你可以參考timeseries_index_schema_conversion_functions.h
. -
在v5.2及以上版本的最新支援的索引型別,
timeseries collection
會儲存使用者原始的索引定義到變換後的索引定義上。當從底層的bucket collection
的索引對映到timeseries collections
的索引時,會返回使用者原始的索引定義。
當索引被建立後,可以通過
listIndexes
命令或
$indexStats
聚合計劃來檢查。
listIndexes
和
$indexStats
是作用於
timeseries collections
的,執行時,它們會在內部將底層的
bucket collection
的索引轉化成
timeseries
格式的索引,並返回。比如,當我們在後設資料欄位中定義有
mm
的
timeseries collection
上執行
listIndexes
命令時,底層的
bucket collection
的
{meta:1}
索引,將會以
{mm:1}
格式返回。
dropIndex
和
collMod
(hidden: <bool>, expireAfterSeconds: <num>)
也同樣支援在
timeseries collection
上。
時間欄位上支援的索引型別:
後設資料欄位和後設資料子欄位支援的索引型別:
-
支援所有時間欄位上支援的索引型別
-
v5.2及以上版本支援2d 索引
-
v5.2及以上版本支援2dsphere 索引
-
v5.2及以上版本支援 Partial索引
僅在v5.2及以上版本,測量值欄位支援的索引型別:
`timeseries collections
上不支援的索引型別,包括 唯一索引以及
文字索引。
桶目錄
Catalog
為了保證高效地桶(分組)操作,我們在
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的更新)。
粒度
Granularity
timeseries collection
的
granularity
選項在集合建立的時候,可以被設定成
seconds
,
minutes
或者
hours
。後期可通過
colMod
操作來修改這個選項從
seconds
到
minutes
或者從
minutes
到
hours
,除此之外的轉化修改目前都是不支援的。該引數想要表示在已給定的時序型測量資料之間的粗略的時間間隔,同時也用於調節其他內部引數對分組的影響。
單個
bucket
被允許的最大時間跨度,是由
granularity
選項控制,對於
seconds
,最大的時間跨度被設定成1小時,對於
minutes
就是24小時,對於
hours
就是30天。
當通過
BucketCatalog
開啟新的
bucket
時,
_id
裡的時間戳就是等同於
control.min.<time field>
的值,該值是從第一個插入
bucket
的測量資料中根據
granularity
選項來向下近似舍入而得到的。對於
seconds
,它將向下舍入到最接近的分鐘,對於
minutes
,將向下舍入到最接近的小時,對於
hours
,它將向下舍入到最接近的日期。在閏秒和日曆中的其他不規則情況下,這種舍入可能並不完美,並且通常通過對自紀元以來的秒數進行基本模運算來完成,假設每分鐘 60 秒,每小時 60 分鐘,以及每天 24 小時。
更新和刪除
timeseries collection
支援符合以下限制的刪除語句:
-
僅支援
metaField
的屬性的查詢語句 -
支援批量操作
同時更新滿足上面同樣的條件,另外遵循:
-
僅支援
metaField
對應的屬性值 -
更新操作指定一個帶有更新運算子表示式的更新文件(而不是替換文件或者更新的pipeline操作)
-
不支援
upsert:true
操作
這些更新與刪除的執行都會被轉換成相對應的底層的
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"}}
。然後這個轉換後的更新語句就可以像普通的更新操作一樣執行。上面這些轉換流程也適用於刪除操作。
參考文獻
References
MongoDB Blog: Time Series Data and MongoDB: Part 2 - Schema Design Best Practices
關於作者:黃璜
目前就職於上海DerbySoft,主要從事基礎架構中業務流程設計及研發的工作,平時工作中MongoDB使用的較多。
在提升自己外文的能力的同時,也希望為社群做出微小的貢獻。
社群招募
為了讓社群組委會成員和志願者朋友們靈活參與,同時我們為想要深度參與社群建設的夥伴們開設了“招募通道”,如果您想要在社群裡面結交志同道合的技術夥伴,想要通過在社群沉澱有價值的乾貨內容,想要一個展示自己的舞臺,提升自身的技術影響力,即刻加入社群貢獻隊伍~ 點選連結提交申請:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69961190/viewspace-2893716/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 技術乾貨 | 解鎖Redis 時間序列資料的應用Redis
- 技術乾貨收集
- 技術乾貨| 如何在MongoDB中輕鬆使用GridFS?MongoDB
- Redis乾貨|解鎖Redis 時間序列資料的應用Redis
- 阿里技術精華乾貨整理阿里
- 技術乾貨| MongoDB如何查詢Null或不存在的欄位?MongoDBNull
- 技術乾貨 | WebRTC 技術解析之 Android VDMWebAndroid
- 使用MongoDB儲存時間序列資料 - DACMongoDB
- [乾貨分享]1000篇乾貨好文!量子技術——資訊篇
- 技術乾貨|如何利用 ChunJun 實現資料實時同步?
- 技術乾貨:RabbitMQ面試題及答案MQ面試題
- 技術乾貨:ActiveMQ面試題及答案MQ面試題
- [乾貨分享]1000篇乾貨好文!量子技術——進階篇
- 【技術乾貨】時速雲企業級容器PaaS技術沙龍 第八期
- 前端面試題乾貨集合前端面試題
- 技術乾貨 | 如何選擇上班路線最省時間?從A/B測試數學原理說起
- 【時間序列分析】01. 時間序列·平穩序列
- 技術乾貨:Hadoop面試題及答案Hadoop面試題
- 2020文章合集 技術乾貨
- 技術乾貨 | 漫遊Linux塊IOLinux
- 乾貨!天翼雲DPU技術解碼
- 【同行說技術】教你玩轉iOS的5篇技術乾貨iOS
- Java集合乾貨——CopyOnWriteArrayList原始碼分析Java原始碼
- Java集合乾貨——ArrayList原始碼分析Java原始碼
- [乾貨分享]1000篇乾貨好文!量子技術——專家觀點篇
- 技術乾貨:spring boot面試題及答案Spring Boot面試題
- 「技術乾貨」Pontus-用友雲限流服務
- 技術乾貨 | WebRTC ADM 原始碼流程分析Web原始碼
- 技術乾貨|品高雲的SDN實踐
- 乾貨!谷歌推薦的技術能力提升指南谷歌
- 【技術乾貨+限時活動】openstack原理及在華為雲中的應用
- Java集合乾貨1——ArrayList原始碼分析Java原始碼
- 時間序列分析
- 技術乾貨:Tomcat面試題彙總及答案Tomcat面試題
- 技術乾貨:Kotlin面試題彙總及答案Kotlin面試題
- 乾貨 | 知識圖譜的技術與應用
- 乾貨 | 京東技術中臺的Flutter實踐之路Flutter
- Spring Boot乾貨系列總綱 | 掘金技術徵文Spring Boot