迪图
发布于 2026-10-20 / 17 阅读
0
0

GIS 数据格式选型:GeoJSON、GeoPackage、FlatGeobuf 与 PMTiles

GIS 数据格式选型:GeoJSON、GeoPackage、FlatGeobuf 与 PMTiles

选错格式的代价不只是文件变大,还包括索引丢失、投影丢失、并发写入失败。这篇讲清楚每种格式的存在意义。

为什么格式选择比想象中重要

一个真实事故:某项目用 GeoJSON 存 300 万个面要素的行政边界。GeoJSON 存不下(单文件 4GB),于是拆成 100 个文件分片。结果是:

  • 没有空间索引,每个空间查询都是全量扫描

  • 每次带坐标转换都要遍历全部 300 万个几何

  • 前端加载时一次性拉取,页面白屏 40 秒

同样的数据如果用 GeoPackage:单文件、索引内置、流式读取,几百毫秒完成。

格式决定了数据能不能被高效使用。

主流格式对比

格式

类型

空间索引

属性表

坐标系

适用场景

GeoJSON

文本

❌

❌(嵌套)

可选

交换、小数据、API 响应

GeoPackage

SQLite

✅ R-tree 内置

✅ 完整 SQL

✅

单文件数据分发、离线桌面

FlatGeobuf

二进制流

✅ Hilbert 曲线

❌

✅

高压缩比、HTTP Range 流式读取

Shapefile

二进制

⚠️ 外部 .qix

✅ .dbf

✅

遗留系统兼容

PMTiles

单文件瓦片

✅ 内部目录

❌

✅(3857)

底图分发、零运维托管

MVT

二进制瓦片

✅

编码压缩

✅(3857 内)

矢量瓦片传输

GeoJSON:通用但不是万能

GeoJSON 的普及度无可替代——它是 Web 上事实上的地理数据交换格式。但它有三个硬限制:

1. 文件体积:JSON 是文本编码,坐标是十进制度数。典型膨胀 3-5 倍

2. 无空间索引:每次空间查询都是全量扫描

3. 无属性表结构:属性是 JSON 对象,不是表结构,没有类型约束

减小 GeoJSON 体积的实用技巧

// 1. 精度截断——可视化不需要厘米级精度
const round = (v, d = 6) => Math.round(v * 10 ** d) / 10 ** d;

// 2. 移除冗余字段
delete feature.properties.createdAt;
delete feature.properties.internalId;

// 3. 用 MultiPolygon 替代多个 Polygon(减少重复的结构开销)

// 4. 坐标数组而非对象
// ✗ {"type":"Point","coordinates":[-0.1276,51.5072]}   → 31 字节
// ✓ [-0.1276,51.5072]                                   → 18 字节

精度截断是性价比最高的一招。 6 位小数约 0.1 米精度,对绝大多数可视化场景绰绰有余,通常能减 20-30% 体积。

什么时候 GeoJSON 是对的

  • 数据量小(几千要素以内)

  • API 响应格式

  • 需要人类可读、便于调试

  • 前端临时数据交换

如果你的 GeoJSON 超过 10MB,就该考虑换格式了。

GeoPackage:单文件方案的赢家

GeoPackage 是 OGC 标准,构建在 SQLite 上。它的实际优势常被低估:

核心优势:索引随文件走。

Shapefile 的 .qix 是独立文件,极易丢失——数据传了索引没传,查询立刻变慢。GeoPackage 的 R-tree 存在 .gpkg 内部,一体传输。

# 转换并自动构建 R-tree 索引
ogr2ogr -f GPKG output.gpkg input.shp

# 检查索引是否存在
ogrinfo output.gpkg | grep -i rtree

属性表是真正的关系表:

-- 可以直接 JOIN、GROUP BY、建索引
SELECT e.name, count(*) AS cnt
FROM events e
JOIN admin_regions r ON ST_Intersects(e.geom, r.geom)
GROUP BY e.name
ORDER BY cnt DESC
LIMIT 10;

其他特性:

  • 完整的 SQLite SQL 支持

  • 并发写入(虽然 WAL 模式下仍需谨慎)

  • 无坐标系丢失

  • GDAL 支持最完善

局限:单文件写入时不适合高并发。多人同时编辑的场景需要数据库。

FlatGeobuf:高压缩比的新选项

FlatGeobuf 是较新的二进制空间格式,基于 Hilbert 空间填充曲线组织数据。

Hilbert 曲线的性质是:空间上邻近的点,在文件里也邻近。这个特性带来两个直接好处:

1. 压缩率高:坐标序列在文件中连续,相邻值差异小,压缩器能有效利用(二进制 + Zstd 压缩率常达 JSON 的 1/10)

2. HTTP Range 请求:因为数据按空间聚集,可以只请求视口对应的字节区间,而不是下载整个文件

# 生成 FlatGeobuf,启用空间索引
ogr2ogr -f FlatGeobuf data.fgb input.geojson -dsco SPATIAL_INDEX=YES

适合:需要高压缩比又需要浏览器端流式读取的场景。CDN 分发大矢量数据集时优势明显。

局限:无属性表结构,不适合做空间查询分析。它是交换和分发格式,不是分析格式。

PMTiles:底图分发的最优解

PMTiles 是专为"单个文件包含完整瓦片金字塔"设计的格式。它把整个 z/x/y 目录放在文件头,后面接瓦片数据。

核心价值:零运维托管。

# 把 MBTiles 转成 PMTiles
pmtiles convert input.mbtiles output.pmtiles

# 直接在 HTTP 静态服务器上发布,不需要瓦片服务

这意味着一个全球范围的完整底图可以是一个静态文件,放在对象存储上通过 CDN 分发,不需要任何服务端逻辑。

对比传统方式:

方案

文件数

需要服务端

传统 XYZ 瓦片

数十万个

✅ 需要

PMTiles

1 个

❌ 不需要

这是 PMTiles 最大的意义——把底图分发的运维成本降到接近零。

局限:

  • 只支持 EPSG:3857 瓦片

  • 不是分析格式

  • 不支持增量更新(文件是完整快照)

Shapefile:只在遗留场景用

Shapefile 是最老的格式,现在新项目不应该再用它,除非对接遗留系统。

必须知道的三个坑:

1. 多文件:xxx.shp、xxx.shx、xxx.dbf、xxx.prj、xxx.qix……少任何一个都打不开。zip 传输时最容易丢文件

2. 字段名截断:DBF 格式字段名最长 10 个字符,超长被静默截断,导致字段名对不上

3. 编码问题:.cpg 文件缺失时中文字段会乱码

结论:新项目直接用 GeoPackage;如果必须对接 Shapefile,在中间做一次格式转换,不要让它进入你的主链路。

OGC 服务格式:什么时候用

WMS / WFS / WCS 这类不是文件格式,是服务协议。

协议

返回

适用

WMS

服务器渲染的图片

影像、样式固定的专题图

WFS

矢量要素(GML/GeoJSON)

查询、编辑、少量矢量

WMTS

缓存瓦片图片

高并发底图浏览

WCS

栅格数据覆盖

影像分析

关键区别:WMS 是服务端渲染(每次请求生成图片),WMTS 是预先切好的缓存瓦片。对高并发场景,WMTS 便宜得多。

现代 Web 应用越来越少直接消费 WMS/WFS,但如果需要对接传统 GIS 部门的数据,OpenLayers 的 ol.source.ImageWMS、ol.source.TileWFS 能无成本对接。

选型决策树

你的场景是什么?
│
├─ API 响应 / 前端临时数据
│   └─ 数据 < 10MB ────────────► GeoJSON(截断精度 + gzip)
│
├─ 单文件数据分发 / 离线桌面
│   └─ 需要属性分析 ────────────► GeoPackage
│
├─ 大矢量 + CDN 分发 + 流式读取
│   └─ 浏览器端渲染 ────────────► FlatGeobuf
│
├─ 底图 / 静态瓦片金字塔
│   └─ 不想运维瓦片服务 ────────► PMTiles
│
├─ 高并发动态瓦片
│   └─ 数据在 PostGIS ──────────► 实时 ST_AsMVT(MBTiles 缓存)
│
├─ 对接遗留系统
│   └─ 必须 ────────────────────► Shapefile(用完尽快转出)
│
└─ 传统 GIS 平台对接
    └─ 标准要求 ────────────────► WMS / WFS / WMTS

各环节推荐格式

一个典型的 WebGIS 项目里,不同环节用不同格式:

环节

格式

理由

数据库存储

PostGIS(原生 geometry)

索引 + 空间查询

瓦片生成

MVT(实时或预生成)

传输优化

底图分发

PMTiles

零运维

数据交换

GeoPackage

格式保真 + 索引

API 响应

GeoJSON

通用可读

离线交付

FlatGeobuf

压缩比

遗留对接

Shapefile

兼容

不要追求全链路一种格式。 每个环节有自己的最优解,转换成本远低于用错格式的代价。

参考资料

  • GeoPackage 规范 — https://www.geopackage.org/

  • FlatGeobuf — https://github.com/felt/flatgeobuf

  • PMTiles — https://github.com/protomaps/PMTiles

  • OGC Simple Features 标准 — https://www.ogc.org/standards/sf

  • GDAL 文档 — https://gdal.org/


评论