跳到主要内容
实操指南9 分钟阅读

如何搭一条撑得过第二次运行的地理空间数据管道

大多数空间数据管道都能完美地跑通一次。真正重要的设计决策,是让它跑到第二十次时依然可靠。

作者
HuiTu Technology
发布时间

只跑一次的地理空间流程,只能算脚本。只有当同一套流程下个月面对变化了的源数据还能跑通,并且你能立刻判断结果是否可信时,它才算一条数据管道。

把三层拆开

接入、转换、校验三层必须严格分离。混在一起时,源数据格式一变就得改分析逻辑;而校验一旦失败,你也判断不出是哪一层出的问题。

  1. 接入层:抓取并原样存储源数据,不做任何修改,并打上时间戳。这一层绝不做转换。
  2. 转换层:解析、标准化、重投影、关联。过程必须是确定性的,并且可以从存好的原始数据重新跑出来。
  3. 校验层:断言结果满足事先写明的条件。每次运行都执行,而不是等到看着不对劲才跑。

每一处都把坐标系写明白

空间数据管道最常见的故障是悄无声息的投影不匹配。程序不报错,点只是落错了地方,或者算出来的距离单位其实是度——而结果看上去足够合理,于是就这么交付出去了。

-- Constrain the CRS at the table level so bad data cannot be inserted
ALTER TABLE poi
  ADD CONSTRAINT poi_geom_srid CHECK (ST_SRID(geom) = 4326);

-- And measure in a projected system, never in degrees
SELECT id,
       ST_Distance(
         ST_Transform(geom, 32633),
         ST_Transform(:target, 32633)
       ) AS metres
FROM poi;

校验要写成断言,而不是靠肉眼看

每次运行都应当检查一组条件,不满足就大声报错并中断。目的是让你从管道本身得知问题,而不是三周后从使用数据的人那里得知。

一套最小可用的校验清单
校验项触发失败的情况
行数与上一次运行的差异在容差范围内某个来源悄悄改了分页逻辑
所有几何对象都有效自相交或畸形的多边形混进了数据
所有要素都落在研究区域的外接矩形内投影不匹配,或者经纬度被写反了
必填字段的非空率高于阈值页面模板变了,解析程序被打断
重复率落在预期区间内去重主键失效了
没有异常的坐标堆叠地理编码开始回退到中心点

让每一层都是幂等的

同一层跑两次,结果必须和跑一次完全一样。这意味着用 upsert 而不是直接 insert,用确定性的标识符而不是自增序号,除非明确设计,否则不在两次运行之间携带任何状态。没有幂等性,一次跑到一半的失败会把数据留在谁也说不清的状态里。

要做版本管理的不只是代码,还有产出物

  • 为每次运行打上版本号与时间戳,并保留历史产出。
  • 记录每一个输入图层的数据版本,包括那些很少变动的图层。
  • 保存本次使用的参数,让结果可以被精确复现,而不是大致复现。
  • 每次运行输出一份变更日志:新增了什么、删除了什么、修改了什么。

这里说的可复现不是学术上的讲究。当两份分析结论打架时,正是这些版本记录让你能在一小时内查清原因,而不是把两份都弃之不用。

聚合后的输出图层,每次定时运行都会重新生成稀疏密集

一套不跟你对着干的技术栈

我们常用的工具,以及为什么用它
用途工具理由
存储与分析PostgreSQL + PostGIS有空间索引、有约束,而且 SQL 是可以逐句审的
格式转换GDAL / OGR几乎什么格式都能稳定地读和写
数据处理Python + GeoPandas转换逻辑好读,测试也好写
调度编排你手上现成的任何调度器调度器本身很少是真正值得纠结的问题
制图与复核QGIS肉眼快速核查,能抓到断言漏掉的问题
网页端交付矢量瓦片(PMTiles)让大体量图层在浏览器里依然流畅

更多文章

继续阅读

下一步

比起了解方法,更想直接把事做完?

如果文章里描述的问题正好是你遇到的,把具体情况发来,我们会给出工作范围与固定报价。