2. 高频采集数据模型与存储格式
高频采集场景下,数据模型与存储格式的选择直接决定了后续压缩比、查询延迟和运维成本。如果模型设计不当,即使压缩算法再优秀,也难以获得理想的查询性能。本节从时间序列数据模型出发,讨论标签与字段的设计原则,对比列式与行式存储的差异,并分析 Parquet、ORC、Arrow 等格式在高频场景下的适用性。
一、时间序列数据模型
高频采集数据本质上是时间序列:每个采样点由“时间戳 + 一组标识维度 + 若干测量值”构成。以工业振动监测为例,一台设备每秒采集 20000 个加速度采样点,每个点包含时间戳、设备编号、测点位置、通道号以及加速度幅值。若按行存储,每个点都要重复记录设备编号和测点位置,冗余极大。
时间序列数据模型通常采用“标签集(Tag Set)+ 字段集(Field Set)+ 时间戳”的结构。标签是用于检索和分组的维度,如设备编号、测点位置、通道号;字段是实际测量值,如加速度、温度、电压。标签的基数决定了时间线的数量,字段的数量决定了每条时间线的宽度。在高频场景中,标签基数往往不大,但字段数量可能很多,且采样频率极高。
一个关键设计原则是:标签用于过滤和分组,字段用于聚合和计算。标签应当选择低基数、查询频繁的维度;字段应当选择高基数、需要参与数值计算的测量值。如果把高基数的测量值误设为标签,会导致时间线爆炸,索引膨胀,查询性能急剧下降。
二、标签与字段设计
标签设计需要关注三个问题:基数、查询模式和存储成本。基数是指某个标签不同取值的数量。设备编号可能有几千个,测点位置可能有几十个,通道号通常只有几个。标签基数越高,索引越大,查询时需要扫描的时间线越多。因此,高频场景下应尽量控制标签基数,必要时将高基数维度拆分为独立字段或采用分片策略。
字段设计需要关注数据类型和精度。高频采集数据通常以浮点数为主,但并非所有字段都需要双精度。加速度幅值可以用 float32 表示,温度可以用 int16 表示,状态码可以用 uint8 表示。合理选择数据类型可以显著降低存储空间。例如,一个 20000 Hz 的振动通道,若用 float64 存储,每秒占用 160 KB;若用 float32,每秒仅占用 80 KB,压缩后差距更大。
此外,字段的排列顺序也会影响压缩效果。将相同类型、相似变化趋势的字段放在一起,有利于列式存储的编码器识别规律,提高压缩比。例如,将多个通道的加速度值连续排列,比交替排列加速度和温度更容易压缩。
三、列式存储与行式存储对比
行式存储将同一时间点的所有字段连续存放,适合写入和整行读取;列式存储将同一字段的所有时间点连续存放,适合按列扫描和聚合。高频采集场景下,查询通常只涉及少数几个字段,且需要按时间范围过滤,列式存储的优势非常明显。
列式存储的另一个优势是压缩。同一字段的数据类型相同、变化规律相似,列式存储可以针对每列独立选择编码方式,如差值编码、游程编码、字典编码等。而行式存储中,不同类型的数据混在一起,压缩器难以找到规律,压缩比通常较低。
但列式存储并非没有代价。写入时,列式存储需要将同一时间点的数据拆分到不同列,增加了写入放大;点查时,需要从多列中分别读取再拼接,延迟可能高于行式存储。因此,在高频采集场景中,通常采用“写入缓冲 + 批量列式落盘”的架构:先在内存中按行缓冲,达到一定批量后按列写入存储文件。
四、Parquet、ORC、Arrow 在高频场景下的适用性
Parquet 是目前高频采集数据落盘最常用的格式。它采用行组、列块、页的三级结构,支持字典编码、游程编码、差值编码等多种编码方式,压缩比通常可以达到 5:1 到 20:1。Parquet 的写入吞吐较高,适合批量落盘;但点查时需要读取整个行组,延迟相对较高。在高频场景中,通常将 Parquet 文件按时间分区,每个分区控制在 128 MB 到 512 MB,查询时通过分区裁剪减少扫描量。
ORC 与 Parquet 类似,但在索引和过滤方面更强。ORC 支持条带级索引、行级索引和布隆过滤器,能够在下推过滤条件时快速跳过不相关的数据块。对于“查询某设备某时间段内加速度超过阈值”的过滤聚合场景,ORC 的性能通常优于 Parquet。但 ORC 的写入吞吐略低于 Parquet,且生态兼容性不如 Parquet 广泛。
Arrow 是内存列式格式,不是持久化存储格式。它的核心价值在于零拷贝和向量化计算:不同查询引擎之间可以通过 Arrow 共享内存数据,避免序列化和反序列化开销。在高频场景中,Arrow 常用于流式处理管道:采集数据先写入 Arrow 缓冲区,经过向量化过滤和聚合后,再批量写入 Parquet 或 ORC 文件。这样既保证了写入吞吐,又降低了查询延迟。
实际选型时,可以遵循以下判断逻辑:如果以批量落盘和离线分析为主,优先选择 Parquet;如果查询以带过滤条件的聚合为主,且对延迟敏感,优先选择 ORC;如果需要在内存中做流式处理或跨引擎共享数据,使用 Arrow 作为中间格式。三者并非互斥,常见架构是“Arrow 缓冲 + Parquet 落盘 + ORC 加速查询”。
五、设计示例:振动监测数据模型
以一台 20000 Hz 振动监测设备为例,设计如下数据模型:标签包括设备编号(基数 5000)、测点位置(基数 20)、通道号(基数 4);字段包括加速度(float32)、温度(int16)、状态码(uint8)。每条时间线每秒产生 20000 个采样点,每个采样点占用 4 + 2 + 1 = 7 字节,每秒约 140 KB。若采用 Parquet 列式存储,加速度列使用差值编码和游程编码,压缩比可达 8:1,每秒实际占用约 17.5 KB。按 5000 台设备、每台 4 通道计算,每天新增数据约 30 GB,压缩后约 3.8 GB,处于可管理范围。
查询时,若需要查询“设备 D0123 在 10:00:00 到 10:00:01 之间的加速度峰值”,系统先通过标签索引定位到 D0123 的时间线,再读取该时间线在指定时间范围内的加速度列,使用向量化计算求峰值。由于只读取一列,且时间范围明确,查询延迟可以控制在毫秒级。
综上,高频采集数据模型的核心是标签与字段的合理分离,存储格式的选择则取决于写入吞吐、查询模式和压缩比之间的权衡。理解这些关系,才能在后续的压缩与查询优化中做出正确决策。