海量轨迹数据存储与分区优化
海量轨迹数据存储与分区优化
轨迹数据是典型的”海量时序 + 空间”双重特征的数据,存储设计不好,查询直接卡死。本文复盘一次轨迹数据存储方案的演进。
轨迹数据的特征
以巡检人员定位为例,每个终端每隔几秒上报一个 GPS 点,一天下来就是海量数据:
- 单终端:约 2 万点/天
- 数百终端:数百万点/天
- 一年:上亿条
轨迹点有三个维度的特征:时间(何时)、空间(在哪)、对象(谁的)。查询场景也围绕这三者展开。
演进一:单表裸奔
最初所有轨迹点堆在一张表里,按时间倒序查最近轨迹还算快(走时间索引)。但一旦查”某个时间段 + 某个区域”的历史轨迹,就要在几千万行里扫描,查询直接超时。
问题本质:单表没有利用时间这个天然的切分维度。
演进二:按时间分区
轨迹数据最有效的优化是按时间分区。PostgreSQL 原生支持分区表:
1 | CREATE TABLE track_points ( |
按时间分区后,查某个月的数据只需扫描对应分区,而不是全表。
演进三:复合优化
时间分区解决了一半问题,但”某区域内的轨迹”仍是难点。进一步优化:
- 空间索引:分区内再建 GiST 空间索引,
ST_DWithin走索引 - 对象维度索引:
(device_id, ts)联合索引,加速单终端轨迹查询 - 冷热分离:热数据(近期)留 SSD,冷数据归档到成本更低的存储
轨迹点的抽稀
还有一个业务层面的优化——轨迹抽稀。原始 GPS 点大量是冗余的(车辆停着不动也在上报)。用道格拉斯-普克算法(Douglas-Peucker)抽稀,保留轨迹形态的前提下把点数量降低一个数量级,存储和渲染压力都大幅下降。
小结
海量轨迹数据的存储设计,核心是抓住时间分区这个主线,再叠加空间索引和对象索引。设计对了,上亿数据也能秒级查询;设计错了,几百万就卡死。这类”数据量驱动的架构决策”,正是后端工程师和架构师的分水岭。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 高晓庄 札记!
