时间序列数据架构设计
本页介绍了在 Bigtable 中存储时序数据的架构设计模式。本页面以设计您的架构为基础,并假设您熟悉该页面上介绍的概念和建议。
时间序列是一系列数据,包括测量值和测量值的记录时间。时间序列的示例包括:
- 计算机内存用量图表
- 通过新闻报道了解的一段时间内的的温度情况
- 一段时间内的股票市场价格
一个设计良好的架构会带来出色的性能和可扩缩性,而一个设计不良的架构则可能会导致系统性能不佳。但是,没有一种架构设计能够完美地贴合所有使用场景。
本页面介绍的模式提供了一个起点。在为时间序列数据设计架构时,最重要的考虑事项是您的独特数据集和计划使用的查询。
在 Bigtable 中存储时间序列数据的基本设计模式如下:
示例数据
为说明模式之间的差异,本页面上的示例假设您存储一个应用的数据,该应用记录气象气球每分钟测量的数据。我们使用“事件”表示同时写入一个或多个单元的单个请求。位置 ID 与 Google Cloud 区域相对应。
测量结果 | 示例 |
---|---|
|
|
压强(帕) | 94587 |
温度(摄氏度) | 9.5 |
湿度(百分比) | 65 |
海拔(米) | 601 |
相关数据 | 示例 |
气球 ID | 3698 |
位置 | asia-southeast1 |
时间戳1 | t2021-03-05-1204 |
时段
在时段模式中,表中的每一行都表示一个时间“段”,例如小时、天或月。行键包含该行中记录的时间段的非时间戳标识符(例如 week49
)以及其他标识数据。
您使用的时段大小(例如分钟、小时或天)取决于您计划使用的查询以及 Bigtable 数据大小限制。例如,如果包含一小时数据的行大于每行 100 MB 的建议大小上限,则表示半小时或一分钟的行可能是更好的选择。
时段模式的优点包括:
提高性能。例如,与将 100 个测量值存储为 100 行相比,如果将 100 个测量值存储在一行中,Bigtable 写入和读取这些测量值的速度会更快。
与行多列少的表相比,以这种方式存储的数据能够更高效地压缩。
缺点包括:
- 时段架构设计模式比单时间戳模式更复杂,其开发需要更多时间和精力。
为新事件添加新列
在此时段模式中,为每个事件向一行写入一个新列,数据存储在列限定符中,而不是作为单元值存储。这意味着,对于每个单元,需要发送列族、列限定符和时间戳,但不发送值。
对示例气象气球数据使用此模式后,每一行包含一个气象气球的一个指标(例如 pressure
)在一周内的所有测量值。每个行键都包含位置、气球 ID、行中记录的指标以及周编号。每当气球报告某个指标的数据时,便在相应的行中添加新列。列限定符包含由单元时间戳标识的分钟的压强测量值(以帕为单位)。
在此示例中,三分钟后,一行可能如下所示:
行键 | 94558 | 94122 | 95992 |
---|---|---|---|
us-west2#3698#pressure#week1 | "" (t2021-03-05-1200) | "" (t2021-03-05-1201) | "" (t2021-03-05-1202) |
此模式的使用场景包括:
您不需要测量时间序列数据的变化。
您希望通过将列限定符用作数据来节省存储空间。
为新事件添加新单元
在此时间模式中,在写入新事件时向现有列添加新单元。此模式可让您利用 Bigtable 的功能,将多个带时间戳的单元存储在给定的行和列中。使用此模式时,请务必指定垃圾回收规则。
以气象气球数据为例,每一行包含一个气象气球在一周内的所有测量值。行键前缀是周的标识符,因此您可以使用单个查询读取多个气球在一周内的所有数据。其他行键片段是气球所在位置和气球的 ID。该表包含一个列族 (measurements
),在该列族中每个测量值类型有一列:pressure
、temperature
、humidity
、altitude
。
每当气球发送其测量值时,应用会将新值写入保存该气球当周数据的行,并向每一列写入带时间戳的额外单元。在一周结束时,每一行中的每一列存储该周中每一分钟的测量值,一共 10080 个单元(在您的垃圾回收政策允许的情况下)。
每一行中的每一列存储该周中每一分钟的测量值。在此示例中,三分钟后,一行中的前两列可能如下所示:
行键 | pressure | temp |
---|---|---|
asia-south2#3698#week1 | 94558 (t2021-03-05-1200) | 9.5 (t2021-03-05-1200) |
94122 (t2021-03-05-1201) | 9.4 (t2021-03-05-1201) | |
95992 (t2021-03-05-1202) | 9.2 (t2021-03-05-1202) |
此模式的使用场景包括:
- 您希望能够测量一段时间内测量值的变化。
单时间戳行
在此模式中,为每个新事件或测量值创建一行,而不是在现有行中向列添加单元。行键后缀是时间戳值。遵循此模式的表通常行多列少,并且一行中的每列只包含一个单元。
单时间戳序列化
在此模式中,将一行的所有数据以序列化格式(例如协议缓冲区 (protobuf))存储在一列中。设计您的架构部分详细介绍了此方法。
例如,如果使用此模式来存储气象气球数据,四分钟后,表可能如下所示:
行键 | measurements_blob |
---|---|
us-west2#3698#2021-03-05-1200 | protobuf_1 |
us-west2#3698#2021-03-05-1201 | protobuf_2 |
us-west2#3698#2021-03-05-1202 | protobuf_3 |
us-west2#3698#2021-03-05-1203 | protobuf_4 |
此模式的优点包括:
存储效率
速度
缺点包括:
读取数据时无法仅检索某些列
需要在读取数据之后进行反序列化处理
此模式的使用场景包括:
您不确定将如何查询数据,或者查询可能波动。
与能够在从 Bigtable 检索数据之前过滤数据相比,您更需要降低费用。
如果将数据存储在多个列中,每个事件包含的测量值可能会超过每行 100 MB 的限制。
单时间戳非序列化
在此模式中,每个事件存储在其自己的行中,即使只记录一个测量值也是如此。列中的数据未序列化。
此模式的优点包括:
通常比时段模式更容易实现。
减少在使用架构之前优化架构花费的时间。
这种模式的缺点通常超出其带来的优势:
使用这一模式时 Bigtable 性能不佳。
以这种方式存储的数据,其压缩效率没有较宽列中数据的压缩效率高。
即使时间戳位于行键末尾,这种模式也会导致热点。
此模式的使用场景包括:
您希望始终检索所有列,但仅检索指定范围的时间戳,但出于某些原因需要不按序列化结构存储数据。
您想要存储不定数量的事件。
使用气象气球示例数据时,列族和列限定符与使用时段和新单元的示例相同。但在此模式中,每个气象气球报告的每组测量值都会写入一个新行。下表显示了使用此模式写入的五行:
行键 | pressure | temperature | humidity | altitude |
---|---|---|---|---|
us-west2#3698#2021-03-05-1200 | 94558 | 9.6 | 61 | 612 |
us-west2#3698#2021-03-05-1201 | 94122 | 9.7 | 62 | 611 |
us-west2#3698#2021-03-05-1202 | 95992 | 9.5 | 58 | 602 |
us-west2#3698#2021-03-05-1203 | 96025 | 9.5 | 66 | 598 |
us-west2#3698#2021-03-05-1204 | 96021 | 9.6 | 63 | 624 |
其他策略
如果您需要向同一数据集发送多个不同的查询,请考虑将数据存储在多个表中,每个表的行键专为一个查询设计。
在某些情况下,您还可以组合使用多个模式。例如,在保证行不会太大的情况下,您可以将序列化数据存储在表示时段的行中。
后续步骤
- 查看规划架构的步骤。
- 了解设计架构的最佳做法。
- 了解您可以从 Bigtable 获得的性能。
- 探索 Key Visualizer 的诊断功能。