架构与实践指南:从桶模型到 BucketCatalog 的完整剖析)
MongoDB 时间序列集合Time-Series Collections架构与实践指南从桶模型到 BucketCatalog 的完整剖析【免费下载链接】mongoThe MongoDB Database项目地址: https://gitcode.com/GitHub_Trending/mo/mongo本文基于 MongoDB 开源仓库src/mongo/db/timeseries/README.md为核心骨架系统讲解时间序列集合的定义方式、底层桶bucket存储模型、三种桶版本与压缩格式、BucketCatalog 内存目录、分桶参数、索引支持、增删改与事务语义等核心机制。读完本文你将理解视图 桶集合的双命名空间架构如何工作掌握timeField/metaField/granularity/expireAfterSeconds等核心选项的配置细节并能从源码层面理解批量写入、桶重开、内存归档、锁条带化等内部实现。1. 什么是 MongoDB 时间序列集合MongoDB 提供了一种专门用于存储时间序列数据的集合类型通过在创建集合时指定 timeseries 集合选项来启用。时间序列集合对外暴露了 插入测量数据measurement、按原始形态查询的简单接口而在内部则将实际数据组织为桶bucket这一中间存储单元从而显著提升写入吞吐、压缩率与查询效率。创建时间序列集合时唯一必需的选项是 timeField——即文档中表示时间戳的顶层字段。 可选地还可以通过 metaField 指定元数据字段用于把属于同一 时间序列的测量数据分组到同一个桶中meta 值相同的测量会被放入同一批桶。此外MongoDB 还通过expireAfterSeconds选项提供基于时间的过期删除机制。1.1 双命名空间架构视图 桶集合一个视图型viewful时间序列集合mydb.mytscoll在 shard catalog 中由两部分组合而成非物化视图mydb.mytscoll以桶集合为数据源具有如下属性视图允许写入仅限插入且插入的每个文档必须包含 time 字段查询视图时会隐式地将底层桶集合中的数据解包unwind回原始的非桶化文档形态。这一步由聚合阶段 $_internalUnpackBucket 完成 关于该阶段以及时间序列查询重写的更多细节参见 query/timeseries/README。系统集合mydb.system.buckets.mytscoll实际数据存储的地方。桶集合中的每个文档代表一段时间窗口内的一组时间序列数据如果创建时定义了元数据字段桶会按元数据组织保证同一桶内所有测量共享同一个 meta 值除了时间范围桶还受测量总数与总大小的约束详见后文 Bucketing Parameters 与桶参数。说明除视图型viewful时间序列之外9.0 还规划了无视图型viewless实现——数据与桶共用同一 命名空间、不再有视图层。具体演进与升级细节可参考 upgrade_downgrade_viewless_timeseries.cpp 与 query/timeseries/README.md。1.2 分片支持时间序列集合同样支持分片。分片相关的实现细节分片键映射、按桶分片等可参见 db/global_catalog/README_timeseries.md。2. 桶集合的文档 Schema2.1 未压缩桶版本 1未压缩桶的结构如下{ _id: Object ID with time component equal to control.min.time field, control: { // 关于测量的统计信息例如各数据字段的 min/max 值 version: 1, // 桶 schema 版本version 1 表示该桶未压缩 min: { time field: 桶内第一条测量的时间按 granularity 向下取整, field0: 所有测量中 field0 的最小值, field1: 所有测量中 field1 的最小值, ... }, max: { time field: 桶内最后一条测量的时间, field0: 所有测量中 field0 的最大值, field1: 所有测量中 field1 的最大值, ... }, closed: bool // 可选通知数据库该文档不会再接收新的测量 }, meta: 创建时指定的 meta 字段值桶内所有测量共享, data: { time field: { 0: 第一条测量的时间, 1: 第二条测量的时间, ... n-1: 第 n 条测量的时间, }, field0: { 0: 第一条测量中 field0 的值, 1: 第二条测量中 field0 的值, ... }, field1: { ... }, ... } }其中data.time field中的元素个数即桶内的测量条数。非 time 字段的数据字段允许出现缺失值即 跳过skip但其元素个数不能超过 time 字段的元素个数。2.2 压缩桶版本 2 与版本 3压缩桶分为 version 2 与 version 3 两种二者的唯一区别在于version 2 桶中 data 字段的条目按时间 排序而 version 3 桶不保证这一点。由于排序有利于读/查询性能系统优先使用 version 2 桶version 3 桶则是在需要维持高写入性能时按需创建。{ _id: Object ID with time component equal to control.min.time field, control: { // 关于测量的统计信息例如各数据字段的 min/max 值 version: 2, // 桶 schema 版本version 2 表示该桶已压缩 min: { time field: 桶内第一条测量的时间按 granularity 向下取整, field0: 所有测量中 field0 的最小值, field1: 所有测量中 field1 的最小值, ... }, max: { time field: 桶内最后一条测量的时间, field0: 所有测量中 field0 的最大值, field1: 所有测量中 field1 的最大值, ... }, closed: bool, // 可选通知数据库该文档不会再接收新的测量 count: int // 桶内包含的测量条数。仅压缩桶存在该字段 }, meta: 创建时指定的 meta 字段值桶内所有测量共享, data: { time field: BinData(7, ...), // BinDataType 7 即 BSONColumn field0: BinData(7, ...), field1: BinData(7, ...), ... } }压缩桶的data字段不再是索引字符串 - 值的普通对象而是每个字段对应一段BSONColumn二进制类型BinData(7)数据。BSONColumn 是 MongoDB 为列式压缩设计的二进制编码 格式其细节可进一步阅读 src/mongo/bson/column/README.md。2.3 桶版本Bucket Versions与版本演进桶可取 V1、V2、V3 三种版本V1未压缩桶内测量不按时间排序V2已压缩且测量按时间排序V3已压缩但不保证测量按时间排序。所谓已压缩指的是桶 data 中的每个字段的测量值都被存储在一个 BSONColumn 中。8.0 起的关键行为变化来自 timeseries README新创建的桶默认是 V2BucketCatalog 中每个 V2/V3 桶为每个数据字段维护一个BSONColumnBuilder它是**只追加 append-only**的新测量只能追加到 builder 末尾如果同一条时间序列的测量以乱序方式进入同一桶在低基数的并发批量加载场景下更常见系统会把 V2 桶提升为 V3 桶。V3 桶行为与 V2 相同唯一区别是其中的测量不保证按时间有序事实上至少存在一条 乱序测量由于无法依赖时间有序性V3 桶上的查询性能可能更差8.0 不再创建新的 V1 桶但升级自旧版本的存量 V1 桶仍受支持。关闭的 V1 桶可以被重开并在写入 更多测量时被压缩——具体来说桶会在 重开的那一刻 被排序并压缩为 V2 随后插入操作在压缩桶上继续执行。2.4 BSONColumnBuilder 与增量二进制每个 V2/V3 桶都持有一个MeasurementMap把桶内每个数据字段不含 meta 字段映射到对应的 BSONColumnBuilder。例如桶的时间字段是time则存在映射time- time 数据对应的 BSONColumnBuilder。BSONColumnBuilder 存储的二进制数据可能代表整个字段的完整 BSONColumn当为该字段添加第一批测量时部分 BSONColumn当向既有字段追加测量时此时二进制只包含新追加的测量。追加场景下可通过调用intermediate()取回代表新增测量的二进制差异diff。这个二进制差异被用来 生成 BSONColumn 的DocDiff用于副本集/分片集群的 oplog 复制。2.5 BSONColumn 的 DocDiff 支持为了避免复制整个压缩桶文档系统利用BSONColumn 追加只改变末尾几个字节的特性使用 DocDiff为每个 字段构造一个 DocDiff包含要追加的新二进制数据以及应复制到既有 BSONColumn 的偏移量。随着 write batch 规模的增大这种方案在 oplog 大小与单条 oplog 条目大小方面都表现更优。DocDiff 的结构如下{ b(inary): { field1: { o(ffset): Number, // 相对既有 BSONColumn 的偏移 d(ata): BinData // 要复制到既有 BSONColumn 的二进制数据 }, ..., fieldN: { o(ffset): Number, // 相对既有 BSONColumn 的偏移 d(ata): BinData // 要复制到既有 BSONColumn 的二进制数据 } } }3. 元数据规范化Metadata Normalization如果文档metaField字段的值包含对象类型数据该数据会被规范化每个嵌套子对象中的字段都会 按字典序排序。这样做的原因是许多应用语言默认或倾向于使用无序字典存储对象字段导致逻辑上属于同一时间序列的 插入呈现出随机字段顺序。规范化后这些文档就能被高效地分到同一个桶中。示例时间序列集合配置了{metaField: m}给定文档{m: {c: 1, b: {f: true, d: 0}}}将被规范化为{m: {b: {d: 0, f: true}, c: 1}}。两点重要说明规范化发生在分片集合的路由routing之前规范化不会应用于$match表达式或其他查询系统位置。因此使用对象相等性过滤的查询可能找不到 预期中的全部文档——因为对象相等性对字段顺序敏感。基于字段顺序的敏感性问题一般不推荐使用对象相等 过滤对时间序列metaField数据更是如此查询应当改为匹配具体的嵌套字段。4. CRUD 操作与 rawData常规 CRUD 操作都可以通过设置rawData命令参数直接与桶化bucketed数据格式交互。例如直接对桶 集合执行 find/aggregate或在 viewless 时间序列上以rawData: true查询原始桶文档详见 query/timeseries/README.md 中对 viewless 的说明。5. 批量插入Batched Inserts当写入路径处理一批插入通常来自insertMany命令时这批数据会 按 meta 值分组并按时间升序排序 以确保高效的分桶与插入。早期版本会严格按照用户指定的顺序逐条进行桶定位bucket targeting如果 用户的批次本身是时间倒序的会导致较差的插入性能与非最优的分桶行为。这一批量排序改造还显著减少了stripe 锁的获取次数从而降低 stripe 锁上的竞争在写入的 staging 阶段每个 meta 值每批大约只获取一次 stripe 锁而不是每条测量获取一次。6. 索引支持Indexes为了支持时间序列集合上能够利用索引而非全表扫描的查询可以在 time 字段、meta 字段以及 meta 子字段上 创建索引。自 v6.0 起时间序列集合的测量字段measurement fields也允许建索引。用户通过createIndex提供的索引键规格会被转换为底层桶集合的 schema。索引规格在时间序列集合与底层桶集合之间的映射细节参见 timeseries_index_schema_conversion_functions.h 其中createBucketsIndexSpecFromTimeseriesIndexSpec将用户索引规格映射为桶集合索引createTimeseriesIndexFromBucketsIndex做反向映射v6.0 及以上新支持的索引类型会在转换后的索引定义中保存原始用户索引定义 在把桶集合索引映射回时间序列集合索引时返回原始定义。索引创建完成后可通过listIndexes命令或$indexStats聚合阶段检查。listIndexes/$indexStats对时间序列集合执行时会在内部转换底层桶集合的索引并返回时间序列 schema 形式的索引。例如底层桶集合 上的{meta: 1}索引在对以mm为元数据字段的时间序列集合执行listIndexes时会显示为{mm: 1}。dropIndex和collModhidden: bool、expireAfterSeconds: num同样支持时间序列集合。6.1 各位置支持的索引类型time 字段上支持的索引类型单字段Single、复合Compound、哈希Hashed、通配符Wildcard、 稀疏Sparse、多键Multikey、带 collation 的索引。metaField 或其子字段上支持的索引类型time 字段上的全部类型外加 v6.0 起的 2d、2dsphere、Partial部分索引。v6.0 起测量字段上支持的索引类型单字段、复合、2dsphere、Partial以及v6.3 起的 TTL 索引 TTL 必须与基于 metaField 或其子字段的partialFilterExpression配合使用。不支持的索引类型unique唯一索引与 text文本索引。7. BucketCatalog内存中的桶目录为了实现高效分桶系统在 BucketCatalog 中维护所有打开的桶。写入方 会把输入批次中的每个文档尝试插入 BucketCatalog后者返回以下两者之一一个BucketCatalog::WriteBatch句柄或可用于从磁盘取回桶以重开reopen的信息。随后第二次尝试插入该文档可能插入到重开的桶中应返回BucketCatalog::WriteBatch。内部地BucketCatalog 为每个桶文档维护一份更新列表。当一批写被提交commit时它会将插入的数据枢轴转换为列式格式即 BSONColumn 结构计算control字段如control.min与control.max所需的更新。对某个桶的首次write batch 提交会插入新形成的文档之后的批次提交执行更新操作——不再生成完整 文档所谓 classic 更新而是直接构造 DocDiff所谓 delta 或 v2 更新。任何绕过 BucketCatalog 直接更新桶文档的路径写入方都必须通过调用timeseries::handleDirectWrite或BucketCatalog::clear通知 BucketCatalog以便其更新内部状态避免写出可能破坏桶格式的数据。7.1 桶重开Bucket Reopening如果首次插入尝试找不到打开的桶或找到的打开桶不适合容纳传入的测量BucketCatalog 会返回一些可用于 从磁盘取回桶并重开的信息某些情况下是归档桶archived bucket的_id其他情况下是一组用于查询的过滤器filters。拿到桶后系统会在内存中重建该桶的内存表示。查询式重开使用的过滤器包含metaField 的精确匹配、timeField 的范围匹配、timeseriesBucketMaxCount与timeseriesBucketMaxSize两个服务参数决定的尺寸过滤器以及control.closed缺失或为false的约束。查询式重开路径依赖{metaField: 1, timeField: 1}索引高效执行。v6.3 新建的时间序列集合默认 创建该索引如果索引不存在则不会使用查询式重开。重开压缩桶时为避免先完全解压、再完全重新压缩系统会从既有的 BSONColumn 二进制直接实例化桶的 BSONColumnBuilder。目前 BSONColumn 只对标量值支持这种优化实例化如果在输入 BSONColumn 二进制中 检测到对象或数组类型BSONColumnBuilder 会对正在重开的指标完全解压并重建 BSONColumn。7.2 桶关闭与归档Bucket Closure and Archival桶可通过设置可选的control.closed标志被永久关闭此后不再有资格被重开。该操作目前仅用于 Atlas Online Archive 场景的手工触发。当 BucketCatalog 的内存占用超过阈值由服务参数timeseriesIdleBucketExpiryMemoryUsageThreshold控制时它会开始归档或关闭空闲桶。空闲桶指 处于打开状态、且没有任何未提交测量等待处理的桶。归档archiving从 BucketCatalog 中移除桶的大部分内存状态但保留一小条记录以便在后续 插入可能落入该桶的测量时更快重开无需查询磁盘。如果归档完所有打开的空闲桶后内存仍超限BucketCatalog 会继续移除归档桶条目以回收更多内存。以 这种方式关闭的桶仍可通过查询式重开恢复。另外两类自动关闭/归档如果新测量会导致桶的最早与最晚时间戳跨度超过集合设置允许的范围BucketCatalog 会关闭该桶 此类桶仍可重开如果新测量的时间戳早于该时间序列当前打开桶的最小时间戳BucketCatalog 会归档该桶。当桶在插入期间被关闭时BucketCatalog 会打开一个新桶或重开旧桶来容纳新测量。8. 分桶参数Bucketing Parameters单个桶允许覆盖的最大时间跨度由bucketMaxSpanSeconds控制。当 BucketCatalog 打开新桶时其_id的时间戳分量等价地其control.min.time field的值取自 插入桶的第一条测量并按bucketRoundingSeconds向下取整。取整通常通过对自 epoch 以来的秒数做 基本的取模运算完成对输入时间戳t与取整值r取整后时间为t - (t % r)。取整与桶时间跨度的 边界情况可参考测试 jstests/core/timeseries/ddl/bucket_timestamp_rounding.js 以及 roundTimestampBySeconds 的实现。8.1 固定分桶 vs granularity 预设用户可以在创建集合时直接设置bucketMaxSpanSeconds与bucketRoundingSeconds以使用固定分桶fixed bucketing。此时要求两个值相等、严格为正、且不超过 31536000365 天。这一校验 在 timeseries_options.cpp 的checkBucketingParameters中强制执行。在大多数情况下用户更希望使用granularity选项。该选项用于表达给定时间序列中测量之间的时间尺度 内置了 seconds、minutes、hours 三档合理预设GranularitybucketRoundingSecondsbucketMaxSpanSecondsSeconds601 分钟3,6001 小时Minutes3,6001 小时86,4001 天Hours86,4001 天2,592,00030 天上表的来源是 getBucketRoundingSecondsFromGranularity 与 getMaxSpanSecondsFromGranularity 两个函数。 注意 hours 档的bucketMaxSpanSeconds以平均 30 天/月估算仅影响内部分桶与查询优化用户不应依赖 或感知该估算值。如果用户创建集合时未指定任何分桶参数默认值为{granularity: seconds}对应 1 分钟取整、1 小时跨度。8.2 collMod 调整限制collMod操作可以调整这些设置前提是净效果为bucketMaxSpanSeconds与bucketRoundingSeconds不减小且数值保持在合法范围内。具体校验逻辑在 isTimeseriesGranularityValidAndUnchangedgranularity 只能单向递增seconds - minutes - hours不允许回退固定分桶参数与 granularity 预设之间可以互相转换只要换算出的秒级参数不因此减小指定 granularity 时不能再同时传bucketRoundingSeconds且bucketMaxSpanSeconds若同时给出 必须等于该 granularity 的默认值。此外分桶参数变化会触发将fixedBucketing重置为false见applyTimeseriesOptionsModifications timeseries_options.cpp。8.3 相关服务参数Server Parameters分桶行为还受到一组服务参数的约束定义在 timeseries.idl参数名默认值说明timeseriesBucketMaxCount1000单个桶最多容纳的测量条数仅 startup 可设≥1timeseriesBucketMaxSize128000125KB单个桶容纳测量的最大字节数仅 startup 可设≥1timeseriesBucketMinCount10因尺寸达到timeseriesBucketMaxSize而需关闭、但未达到该阈值的桶被视为含大测量保持打开以改善分桶性能设为 1 可禁用该行为timeseriesBucketMinSize51205KB系统内存压力高时会降低打包进桶的测量最大字节数该值是允许降到的最低值timeseriesLargeMeasurementThreshold32测量中某个元素大于该阈值字节时按其未压缩大小计入桶大小限制timeseriesInsertMaxRetriesOnDuplicates32因 OID 生成碰撞导致桶文档插入冲突时的自动重试次数timeseriesMaxRetriesForWriteConflictsOnReopening16桶重开时因 WriteConflict 而重试的最大次数timeseriesIdleBucketExpiryMemoryUsageThreshold5BucketCatalog 内存阈值1~100 视为系统内存百分比100 视为字节数≤0 自动恢复默认百分比timeseriesSideBucketCatalogMemoryUsageThreshold104857600100MB侧边桶目录side bucket catalog内存阈值timeseriesIdleBucketExpiryMaxCountPerAttempt3每次尝试因过期而关闭的桶的最大数量≥2此外还有数据完整性校验类参数performTimeseriesCompressionIntermediateDataIntegrityCheckOnReopening默认 true重开压缩桶时做完整性校验、performTimeseriesCompressionIntermediateDataIntegrityCheckOnInsert默认 true及其采样频率...OnInsertFrequency默认 1取值 0~100表示执行校验的百分比概率以及timeseriesDisableStrictBucketValidator/timeseriesLessStrictBucketValidator用于切换桶文档校验器。9. 桶时间戳Bucket Timestamps桶 ObjectID 的时间分量应等于control.min.time字段但ObjectID 类型以 4 字节 unix 秒级时间戳 存储范围 1970~2038可能溢出而 control 块以8 字节毫秒精度时间戳存储。时间戳会在以下情况溢出正的、大于2038-01-17T03:14:07.000Z的时间戳负的、即 1970-01-01T00:00:00.000Z 之前的日期所表示的时间戳。发生溢出时时间序列桶_id字段的最高有效位会被置为 1从而使集合能够快速判断自身包含 扩展范围extended-range时间戳。相关实现参见 timeseries_extended_range.h。另一个易混淆点桶的 ObjectID 与测量的_id时间分量没有内在关联。测量而非桶的_id时间 分量指示的是插入时间而非测量时间。对于实时工作负载二者大致相关但在加载历史数据或处理迟到测量时 二者会发生偏离。10. 更新与删除Updates and Deletes时间序列集合支持任意的更新与删除操作用户可见的行为与普通集合一致。10.1 删除时间序列的用户删除逐桶文档执行桶文档被解包unpack逐条测量对照用户删除谓词检查若存在不需要删除的测量它们会被重新打包回原桶文档相同_id以更新操作落盘若所有测量都匹配删除谓词整个桶文档被删除。如果删除谓词本身就作用于整个桶文档如按 meta 字段精确匹配删除会跳过解包直接针对桶文档执行。10.2 更新与删除类似时间序列的用户更新也是逐桶文档执行不匹配更新谓词的测量会被重新打包回原桶文档相同_id以更新操作落盘匹配谓词的测量会应用用户提供的更新操作并作为新的桶文档插入若所有测量都匹配谓词原桶文档整个被删除。为避免{multi: true}更新时的 Halloween Problem系统使用 Spool Stage 记录扫描阶段返回的所有桶文档的 record id 这配合把更新后的测量插入新桶可避免更新命令看到自身刚更新过的测量。如果查询非选择性且匹配的桶文档 过多spool 阶段在达到最大内存使用限制时会**溢出spill**已匹配桶文档的 record id。由于时间序列更新对存储至少执行两次写入对原桶文档的修改 新桶文档的插入oplog 条目会被打包成 一个applyOps命令以保证操作原子性。时间序列的 upsert 与更新共享同一流程upsert 的测量会生成一个_id。10.3 事务支持时间序列的单条singleton更新与删除支持多文档事务内部用于无分片键的单条更新/删除、分片键 更新以及可重试的时间序列更新/删除。10.4 可重试写Retryable Writes时间序列删除通过既有机制支持可重试写时间序列更新通过 Internal Transaction API 执行以确保对存储的两次写入原子完成。10.5 暂存与提交测量时的错误处理一次时间序列写包含三个阶段每个阶段都有一次独立的 stripe 锁获取Staging暂存修改桶元数据为把测量插入桶目录做准备——不涉及压缩也不把测量写入桶目录Committing提交把测量压缩进合适的桶文档并写入存储Finish收尾修改桶目录使其反映已写入存储的状态。错误示例可继续ContinuableDuplicateKey——批量时间序列插入时 OID 生成发生碰撞不可继续Non-continuable异常例如获取桶集合时的StaleConfig异常。注意服务器内部重试时间序列写与驱动层的外部可重试写retryable writes是两个不同的过程 内部重试机制同时也会处理可重试写。10.6 内存占用计算桶、BucketCatalog 以及其他时间序列内部组件Stripes、BucketMetadata 等的内存占用都通过 Tracking Allocator 计算。10.7 冻结桶Freezing Buckets当桶压缩失败时系统会失败本次插入提示用户重试写入并冻结压缩失败的桶。桶一旦被冻结 将不再尝试写入。10.8 锁条带化Stripes桶目录使用锁条带化lock striping技术为跨 CRUD 操作的桶提供高效的并行与同步。时间序列集合中 潜在数量巨大成千上百万的 meta 值会被哈希到硬编码的 32 个条带上每个 meta 值总是映射到同一个 条带。该哈希函数对用户不透明且不可配置。自 8.2 起每次对集合执行时间序列写都会按上文三个阶段获取 3 次 stripe 锁。每个桶最多包含timeseriesBucketMaxCount1000条测量时间跨度不超过bucketMaxSpanSeconds桶目录 维持每个唯一 meta 值至多 1 个打开桶的不变量。哈希函数可能无法把客户端写入均匀分布到各条带但 总体上由于条带数量通常与数据库服务器核心数相当甚至更多stripe 竞争不太可能成为瓶颈当然若工作负载 访问的众多桶meta 值恰好映射到同一条带特定条带可能成为热点。8.2 在持有 stripe 锁期间只做少量 刻意的工作进一步减轻了 stripe 竞争的影响。Stripe 结构体 存储了 BucketCatalog 的大部分核心组件openBucketsById按 BucketId 索引的打开桶、openBucketsByKey按 BucketKey 索引、idleBuckets无未完成写入的打开桶、archivedBuckets已归档但可接收更多测量的桶以及outstandingReopeningRequests进行中的重开请求用于协调磁盘访问。其中的数据结构大多使用 tracking 容器共同构成 Bucket Catalog 的内存占用见 bucket_catalog::getMemoryUsage。11. 常见术语表Glossarybucket桶同一 meta 数据、有限时间段内的一组测量。active bucket活动桶已归档或打开的桶构成 BucketCatalog 管理的基数。archived bucket归档桶位于磁盘、但在内存中保留一小条记录以支持免查询高效重开的桶。向其中添加新测量需要从磁盘物化数据。closed bucket关闭桶仅存在于磁盘的桶。可能因以下原因关闭过大测量条数或物理大小、内存压力。frozen bucket冻结桶因无法压缩而不再有资格接收新测量的桶。idle bucket空闲桶打开但没有任何待提交未提交测量的桶。与内存压力下的桶关闭相关。open bucket打开桶驻留内存、可高效接收新测量的桶。bucket collection桶集合存储时间序列集合底层桶的系统集合。复制、分片和索引都在桶集合的桶层级进行。measurement测量某个特定时刻的一组相关键值对。meta-data元数据时间序列中很少随时间变化、用于标识整条时间序列的键值对。time-series时间序列一段时间内按时间排列的测量序列。time-series collection时间序列集合包含时间序列数据的集合可实现为 viewful 或 viewless 两种形态默认指 viewful 实现中的视图。viewful time-series视图型时间序列通过一个可写的非物化视图形式的集合类型提供时间序列数据的设置该视图可存储和查询多条具有不同 meta 数据的时间序列。viewless time-series无视图型时间序列时间序列数据与桶使用同一命名空间的设置不使用视图。12. 参考资料MongoDB Blog: Time Series Data and MongoDB: Part 2 - Schema Design Best Practices时间序列查询重写与$_internalUnpackBucket的详细说明src/mongo/db/query/timeseries/README.md分片相关实现细节src/mongo/db/global_catalog/README_timeseries.mdBSONColumn 列式二进制格式src/mongo/bson/column/README.md【免费下载链接】mongoThe MongoDB Database项目地址: https://gitcode.com/GitHub_Trending/mo/mongo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考