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 秒時間間隔之后,過期數據可能會存在一段時間。