第 1 章:PostGIS 简介
第 1 章:PostGIS 简介
1.1 什么是 PostGIS
PostGIS 是 PostgreSQL 的空间数据库扩展,它为 PostgreSQL 添加了对地理空间对象的支持。通过 PostGIS,你可以在关系型数据库中存储、查询和分析地理空间数据,将传统的关系数据与空间数据无缝结合。
核心能力
| 能力 | 说明 | 示例函数 |
|---|---|---|
| 空间数据存储 | 存储点、线、面等几何对象 | ST_GeomFromText() |
| 空间关系判断 | 判断几何对象之间的拓扑关系 | ST_Intersects(), ST_Contains() |
| 空间测量 | 计算距离、面积、长度 | ST_Distance(), ST_Area() |
| 空间分析 | 缓冲区、叠加、融合等分析操作 | ST_Buffer(), ST_Union() |
| 坐标转换 | 不同坐标系之间的转换 | ST_Transform() |
| 栅格数据 | 支持栅格(raster)数据存储与分析 | ST_MapAlgebra() |
| 拓扑建模 | 支持拓扑数据模型 | Topology 类型 |
版本历史与里程碑
| 版本 | 年份 | 关键特性 |
|---|---|---|
| 1.0 | 2001 | 首次发布,基础几何类型 |
| 2.0 | 2012 | 引入 Geography 类型、栅格支持 |
| 3.0 | 2019 | 性能大幅提升、并行查询支持 |
| 3.4 | 2023 | 改进的 3D 支持、增强的 GeoJSON 处理 |
-- 查看当前 PostGIS 版本
SELECT PostGIS_Version();
-- 输出示例: 3.4 USE_GEOS=1 USE_PROJ=1 USE_STATS=1
1.2 OGC 标准与 Simple Features
OGC(Open Geospatial Consortium,开放地理空间联盟)是一个国际标准化组织,制定了地理空间数据的互操作标准。PostGIS 实现了 OGC 的 Simple Feature Access (SFA) 规范。
Simple Feature 模型
SFA 规范定义了以下核心几何类型:
Geometry (抽象基类)
├── Point -- 点
├── LineString -- 线
├── Polygon -- 面
├── MultiPoint -- 多点集合
├── MultiLineString -- 多线集合
├── MultiPolygon -- 多面集合
└── GeometryCollection -- 混合几何集合
Well-Known Text (WKT) 表示
SFA 规范定义了几何对象的文本表示格式——WKT(Well-Known Text):
-- 点 (Point)
SELECT ST_GeomFromText('POINT(116.4074 39.9042)'); -- 北京天安门
-- 线 (LineString)
SELECT ST_GeomFromText('LINESTRING(116.40 39.90, 116.42 39.92, 116.44 39.91)');
-- 面 (Polygon) — 注意首尾坐标相同,形成闭合环
SELECT ST_GeomFromText('POLYGON((116.38 39.90, 116.42 39.90, 116.42 39.93, 116.38 39.93, 116.38 39.90))');
-- 多面 (MultiPolygon)
SELECT ST_GeomFromText('MULTIPOLYGON(((0 0, 1 0, 1 1, 0 1, 0 0)), ((2 2, 3 2, 3 3, 2 3, 2 2)))');
Well-Known Binary (WKB)
WKB 是几何对象的二进制表示,适合程序间高效传输:
-- 输出 WKB 的十六进制表示
SELECT ST_AsHexEWKB(ST_GeomFromText('POINT(116.4074 39.9042)'));
-- 从 WKB 创建几何
SELECT ST_GeomFromEWKB('\x01010000005839b4c876be5d407b14ae47e1524340');
注意: WKT 和 WKB 是 PostGIS 中最基础的两种数据格式,几乎所有操作都围绕它们展开。
1.3 空间数据库 vs 文件型 GIS
传统 GIS 使用 Shapefile、GeoJSON 等文件格式存储空间数据。空间数据库则将数据纳入关系型数据库管理体系。
对比表
| 特性 | 文件型 GIS (Shapefile) | 空间数据库 (PostGIS) |
|---|---|---|
| 并发访问 | 不支持 | 完整 ACID 事务支持 |
| 数据量级 | 单文件约 2GB | 无硬性限制(TB 级) |
| 空间查询 | 需加载到内存 | 索引加速,按需查询 |
| 属性查询 | 有限 SQL 支持 | 完整 SQL 支持 |
| 数据关联 | 需要额外处理 | 与业务表 JOIN |
| 版本控制 | 文件复制 | 数据库备份与恢复 |
| 安全控制 | 文件权限 | 行级安全策略 (RLS) |
| 扩展性 | 差 | 支持分区、复制、集群 |
典型架构
┌──────────────┐ ┌──────────────────┐ ┌──────────────┐
│ 前端应用 │────▶│ PostGIS 数据库 │────▶│ 空间分析引擎 │
│ (Leaflet等) │ │ (PostgreSQL) │ │ (GEOS/PROJ) │
└──────────────┘ └──────────────────┘ └──────────────┘
│ │ │
▼ ▼ ▼
GeoJSON API SQL 查询 拓扑/投影计算
1.4 PostGIS 生态系统
PostGIS 不是孤立的,它与一系列开源工具组成了强大的空间数据生态:
核心依赖库
| 库 | 功能 | PostGIS 中的角色 |
|---|---|---|
| GEOS | 几何引擎 | 几何操作的底层实现(交集、缓冲区等) |
| PROJ | 坐标投影库 | 坐标系统转换 |
| GDAL | 栅格数据抽象库 | 栅格数据读写 |
| SFCGAL | 高级几何库 | 3D 操作、高级拓扑运算 |
| CGAL | 计算几何库 | SFCGAL 的后端 |
相关工具链
-- 查看 PostGIS 编译时的依赖支持
SELECT name, default_version, installed_version
FROM pg_available_extensions
WHERE name IN ('postgis', 'postgis_topology', 'postgis_raster',
'pgrouting', 'address_standardizer', 'postgis_sfcgal');
| 工具 | 用途 |
|---|---|
| shp2pgsql / pgsql2shp | Shapefile 导入导出 |
| ogr2ogr (GDAL) | 多格式空间数据转换 |
| raster2pgsql | 栅格数据导入 |
| pgRouting | 路径规划扩展 |
| pg_tileserv | 矢量瓦片服务 |
| pg_featureserv | OGC API - Features 服务 |
1.5 适用场景与不适用场景
✅ 推荐使用 PostGIS 的场景
场景 1:位置服务(LBS)
- 附近的人/店铺搜索
- 地理围栏(Geofencing)判断
- 配送范围计算
-- 查找某点 3 公里范围内的所有门店
SELECT name, address,
ST_Distance(
geom::geography,
ST_SetSRID(ST_MakePoint(116.4074, 39.9042), 4326)::geography
) AS distance_m
FROM stores
WHERE ST_DWithin(
geom::geography,
ST_SetSRID(ST_MakePoint(116.4074, 39.9042), 4326)::geography,
3000
)
ORDER BY distance_m;
场景 2:城市规划与管理
- 地块叠加分析
- 基础设施覆盖分析
- 人口密度热力图
场景 3:物流与运输
- 路径优化
- 车辆追踪
- 仓储选址分析
场景 4:环境与自然资源
- 土地利用变化监测
- 洪水淹没分析
- 生态保护区管理
场景 5:商业智能
- 市场区域划分
- 竞品地理分布分析
- 销售热区识别
❌ 不推荐使用 PostGIS 的场景
| 场景 | 替代方案 | 原因 |
|---|---|---|
| 海量实时轨迹流 | TimescaleDB + PostGIS 或 MongoDB | 高频写入压力大 |
| 瓦片地图渲染 | MapServer / GeoServer | 数据库不是最优的渲染引擎 |
| 卫星影像处理 | Google Earth Engine / Rasterio | 专业工具更高效 |
| 简单坐标存储 | MongoDB 2dsphere / Redis GEO | 轻量方案更简单 |
| 超大规模图计算 | Neo4j Spatial / Apache Spark | 图数据库更适合关系遍历 |
1.6 第一个空间查询
让我们通过一个完整的示例来感受 PostGIS 的能力。
创建示例表
-- 创建城市表
CREATE TABLE cities (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
province VARCHAR(50),
population INTEGER,
geom GEOMETRY(Point, 4326)
);
-- 插入示例数据
INSERT INTO cities (name, province, population, geom) VALUES
('北京', '北京', 21890000, ST_SetSRID(ST_MakePoint(116.4074, 39.9042), 4326)),
('上海', '上海', 24870000, ST_SetSRID(ST_MakePoint(121.4737, 31.2304), 4326)),
('广州', '广东', 18680000, ST_SetSRID(ST_MakePoint(113.2644, 23.1291), 4326)),
('深圳', '广东', 17560000, ST_SetSRID(ST_MakePoint(114.0579, 22.5431), 4326)),
('成都', '四川', 20940000, ST_SetSRID(ST_MakePoint(104.0668, 30.5728), 4326)),
('杭州', '浙江', 12200000, ST_SetSRID(ST_MakePoint(120.1551, 30.2741), 4326)),
('武汉', '湖北', 12330000, ST_SetSRID(ST_MakePoint(114.3055, 30.5928), 4326)),
('西安', '陕西', 13000000, ST_SetSRID(ST_MakePoint(108.9402, 34.2613), 4326));
-- 创建空间索引
CREATE INDEX idx_cities_geom ON cities USING GIST (geom);
执行空间查询
-- 查询 1:计算北京到上海的直线距离(米)
SELECT ST_Distance(
(SELECT geom FROM cities WHERE name = '北京')::geography,
(SELECT geom FROM cities WHERE name = '上海')::geography
) / 1000 AS distance_km;
-- 输出: ~1068 公里
-- 查询 2:查找北京 1500 公里范围内的城市
SELECT name, province, population,
ROUND(ST_Distance(geom::geography,
ST_SetSRID(ST_MakePoint(116.4074, 39.9042), 4326)::geography
) / 1000) AS distance_km
FROM cities
WHERE ST_DWithin(
geom::geography,
ST_SetSRID(ST_MakePoint(116.4074, 39.9042), 4326)::geography,
1500000
)
ORDER BY distance_km;
-- 查询 3:生成 GeoJSON 输出
SELECT jsonb_build_object(
'type', 'FeatureCollection',
'features', jsonb_agg(
jsonb_build_object(
'type', 'Feature',
'geometry', ST_AsGeoJSON(geom)::jsonb,
'properties', jsonb_build_object(
'name', name,
'province', province,
'population', population
)
)
)
) AS geojson
FROM cities;
1.7 关键术语表
| 术语 | 英文 | 说明 |
|---|---|---|
| 几何类型 | Geometry Type | 点、线、面等空间对象类型 |
| 地理类型 | Geography Type | 基于球面的地理坐标类型 |
| 空间参考系统 | Spatial Reference System (SRS) | 坐标系统的标准化定义 |
| SRID | Spatial Reference System Identifier | 空间参考系统的唯一标识符 |
| WKT | Well-Known Text | 几何对象的文本表示格式 |
| WKB | Well-Known Binary | 几何对象的二进制表示格式 |
| 拓扑关系 | Topological Relation | 几何对象之间的空间关系(相交、包含等) |
| 缓冲区 | Buffer | 距某几何对象指定距离的区域 |
| 叠加分析 | Overlay Analysis | 两个图层的空间叠加运算 |
| 空间索引 | Spatial Index | 加速空间查询的索引结构 |
1.8 本章小结
| 要点 | 说明 |
|---|---|
| PostGIS 是什么 | PostgreSQL 的空间扩展,实现 OGC SFA 规范 |
| 核心能力 | 空间存储、查询、分析、坐标转换 |
| 数据格式 | WKT(文本)和 WKB(二进制) |
| 适用场景 | LBS、城市规划、物流、环境监测、商业智能 |
| 生态系统 | GEOS + PROJ + GDAL + pgRouting 等 |