PostGIS 完全指南 / 第 3 章:架构与核心概念
第 3 章:架构与核心概念
3.1 PostGIS 架构总览
PostGIS 的架构分为三层,每一层都承担不同的职责:
┌─────────────────────────────────────────────────┐
│ SQL 接口层 │
│ ST_Intersects(), ST_Buffer(), ST_Distance() │
├─────────────────────────────────────────────────┤
│ PostGIS 核心层 │
│ 几何类型系统 | 空间索引 | 坐标转换 | 栅格引擎 │
├─────────────────────────────────────────────────┤
│ 依赖库层 │
│ GEOS | PROJ | GDAL | SFCGAL │
└─────────────────────────────────────────────────┘
数据存储模型
PostGIS 通过向 PostgreSQL 添加自定义类型和函数来实现空间功能:
-- 查看 PostGIS 注册的类型
SELECT typname, typtype
FROM pg_type
WHERE typname IN ('geometry', 'geography', 'box2d', 'box3d');
-- 查看 PostGIS 注册的函数数量
SELECT count(*) AS function_count
FROM pg_proc p
JOIN pg_namespace n ON p.pronamespace = n.oid
WHERE n.nspname = 'public'
AND p.proname LIKE 'st_%';
3.2 几何类型 (Geometry) vs 地理类型 (Geography)
PostGIS 提供两种核心空间类型,理解它们的区别至关重要。
Geometry 类型
- 基于笛卡尔平面坐标系
- 单位取决于坐标系定义(可能是度、米、英尺等)
- 支持所有几何操作
- 计算速度快
- 适合投影坐标系(如 UTM)下的局部分析
Geography 类型
- 基于球面坐标系(WGS84 椭球体)
- 单位始终为米
- 仅支持有限的几何操作
- 计算较慢(需椭球体计算)
- 适合大范围距离/面积计算
对比表
| 特性 | Geometry | Geography |
|---|---|---|
| 坐标系 | 笛卡尔平面 | 球面椭球体 |
| 距离单位 | 取决于 SRID | 始终为米 |
| 支持的 SRID | 任意 | 仅 4326 (WGS84) |
| 空间索引 | GiST | GiST |
| 可用函数 | 全部 ST_* 函数 | 有限(ST_Distance, ST_DWithin, ST_Area, ST_Length 等) |
| 计算精度 | 局部高精度 | 全球高精度 |
| 性能 | 快 | 慢(椭球体计算开销大) |
类型转换
-- Geometry -> Geography
SELECT geom::geography FROM cities WHERE name = '北京';
-- Geography -> Geometry
SELECT geog::geometry FROM geog_table;
-- 使用 Geography 计算真实距离(米)
SELECT ST_Distance(
ST_SetSRID(ST_MakePoint(116.4074, 39.9042), 4326)::geography,
ST_SetSRID(ST_MakePoint(121.4737, 31.2304), 4326)::geography
) / 1000 AS distance_km;
-- 输出: ~1068 (公里)
选择指南
需要精确的局部分析? ──是──▶ 使用 Geometry + 投影坐标系
│
否
│
需要计算大范围距离? ──是──▶ 使用 Geography
│
否
│
需要复杂几何操作? ──是──▶ 使用 Geometry
│
否
▼
根据数据源决定
3.3 空间参考系统 (SRS)
空间参考系统(Spatial Reference System)定义了坐标与地球表面位置之间的对应关系。
SRS 三要素
| 要素 | 说明 | 示例 |
|---|---|---|
| 基准面 (Datum) | 地球椭球体模型 | WGS84, CGCS2000 |
| 坐标类型 | 地理坐标或投影坐标 | 经纬度 / 平面 XY |
| 单位 | 度、米、英尺等 | 度 (°), 米 (m) |
常用 SRID
| SRID | 名称 | 类型 | 覆盖范围 | 常用场景 |
|---|---|---|---|---|
| 4326 | WGS 84 | 地理坐标 | 全球 | GPS 数据、Web 地图 |
| 3857 | Web Mercator | 投影坐标 | 全球 | Web 地图瓦片 |
| 4490 | CGCS 2000 | 地理坐标 | 中国 | 国内测绘标准 |
| 4547 | CGCS 2000 / 3-degree GK zone 39 | 投影坐标 | 中国 117°带 | 国内工程测量 |
| 32650 | WGS 84 / UTM zone 50N | 投影坐标 | 东经 114°-120° | 中国东部沿海 |
| 2154 | RGF93 / Lambert-93 | 投影坐标 | 法国 | 法国国内数据 |
-- 查看 SRID 详细信息
SELECT srid, auth_name, auth_srid, srtext
FROM spatial_ref_sys
WHERE srid = 4326;
-- 搜索中国相关的坐标系
SELECT srid, srtext
FROM spatial_ref_sys
WHERE srtext ILIKE '%china%' OR srtext ILIKE '%CGCS%'
LIMIT 10;
3.4 GEOS 几何引擎
GEOS (Geometry Engine - Open Source) 是 PostGIS 的核心几何计算库,它实现了 OGC Simple Feature 规范中的所有几何操作。
GEOS 提供的核心能力
| 能力 | 函数示例 |
|---|---|
| 拓扑关系 | ST_Intersects, ST_Contains, ST_Within, ST_Crosses |
| 几何操作 | ST_Union, ST_Intersection, ST_Difference, ST_SymDifference |
| 缓冲分析 | ST_Buffer |
| 几何构造 | ST_Centroid, ST_ConvexHull, ST_ConcaveHull |
| 几何测量 | ST_Area, ST_Length, ST_Distance |
| 几何验证 | ST_IsValid, ST_IsValidReason, ST_MakeValid |
-- GEOS 版本信息
SELECT PostGIS_GEOS_Version();
-- 示例:创建缓冲区
SELECT ST_AsText(ST_Buffer(ST_GeomFromText('POINT(0 0)'), 10));
3.5 PROJ 坐标投影库
PROJ 负责坐标系统之间的转换,它是 PostGIS 中 ST_Transform 函数的底层实现。
-- PROJ 版本信息
SELECT PostGIS_PROJ_Version();
-- 将北京坐标从 WGS84 (4326) 转换为 CGCS2000 三度带 39 带 (4547)
SELECT ST_AsText(
ST_Transform(
ST_SetSRID(ST_MakePoint(116.4074, 39.9042), 4326),
4547
)
);
-- 输出: POINT(447963.89 4418554.07) (单位:米)
3.6 空间索引体系
空间索引是 PostGIS 性能的基石。没有空间索引,空间查询将退化为全表扫描。
GiST 索引
GiST (Generalized Search Tree) 是 PostgreSQL 的通用搜索树框架,PostGIS 在此基础上实现了空间索引。
-- 创建 GiST 空间索引
CREATE INDEX idx_cities_geom ON cities USING GIST (geom);
-- 索引支持的操作符
-- && — 边界框相交
-- @ — 被包含于
-- ~ — 包含
-- <-> — 距离排序(KNN 查询)
-- |&> | <& — 各种边界框关系
SP-GiST 索引
SP-GiST (Space-Partitioned GiST) 适合非平衡数据结构(如四叉树):
-- SP-GiST 索引(适合大量随机分布的点数据)
CREATE INDEX idx_points_spgist ON points USING SPGIST (geom);
BRIN 索引
BRIN (Block Range Index) 适合物理有序的大表(如时间序列空间数据):
-- BRIN 索引(极小的索引体积,适合有序插入的大表)
CREATE INDEX idx_events_brin ON events USING BRIN (geom);
索引对比
| 索引类型 | 大小 | 创建速度 | 查询性能 | 适用场景 |
|---|---|---|---|---|
| GiST | 中等 | 中等 | 优秀 | 通用场景,首选 |
| SP-GiST | 中等 | 快 | 优秀 | 大量随机点 |
| BRIN | 极小 | 极快 | 良好 | 有序大表 |
3.7 几何对象内部结构
Bounding Box(边界框)
每个几何对象都有一个最小边界矩形(MBR),用于快速的空间过滤:
-- 查看几何对象的边界框
SELECT ST_Extent(geom) AS bbox FROM cities;
-- 输出: BOX(104.0668 22.5431,121.4737 39.9042)
-- ST_Envelope 返回几何对象
SELECT ST_AsText(ST_Envelope(
ST_GeomFromText('LINESTRING(0 0, 10 10)')
));
-- 输出: POLYGON((0 0,10 0,10 10,0 10,0 0))
几何对象元数据
SELECT
name,
ST_GeometryType(geom) AS type, -- 几何类型
ST_NDims(geom) AS ndims, -- 维度 (2D/3D)
ST_SRID(geom) AS srid, -- 坐标系
ST_NumPoints(geom) AS npoints, -- 坐标点数量
ST_IsEmpty(geom) AS is_empty, -- 是否为空
ST_IsValid(geom) AS is_valid, -- 是否有效
ST_IsSimple(geom) AS is_simple -- 是否简单
FROM cities;
3.8 维度模型
PostGIS 支持 2D、3D 和 4D(含测量值 M)几何对象:
-- 2D 几何
SELECT ST_GeomFromText('POINT(116.40 39.90)');
-- 3D 几何 (带 Z 坐标 — 高程)
SELECT ST_GeomFromText('POINT Z(116.40 39.90 50.0)');
-- 4D 几何 (带 Z 和 M — 测量值)
SELECT ST_GeomFromText('POINT ZM(116.40 39.90 50.0 100.0)');
-- 查询维度
SELECT ST_NDims(ST_GeomFromText('POINT Z(1 2 3)'));
-- 输出: 3
-- 获取 Z 坐标
SELECT ST_Z(ST_GeomFromText('POINT Z(116.40 39.90 50.0)'));
-- 输出: 50.0
3.9 GEOMETRY_COLUMNS 元数据表
PostGIS 维护了一个 geometry_columns 视图,记录所有空间列的元数据:
-- 查看所有空间表
SELECT f_table_schema, f_table_name, f_geometry_column,
coord_dimension, srid, type
FROM geometry_columns
WHERE f_table_schema = 'public';
-- 查看特定表的空间列信息
SELECT * FROM geometry_columns
WHERE f_table_name = 'cities';
手动注册空间列
-- 如果表已存在但未注册空间列
SELECT Populate_Geometry_Columns('public.my_table'::regclass);
-- 或手动注册
INSERT INTO geometry_columns
(f_table_catalog, f_table_schema, f_table_name, f_geometry_column,
coord_dimension, srid, type)
VALUES
('', 'public', 'my_table', 'geom', 2, 4326, 'POINT');
3.10 spatial_ref_sys 表
spatial_ref_sys 是 PostGIS 的坐标系定义表,包含数千种坐标系:
-- 总共支持多少种坐标系?
SELECT count(*) FROM spatial_ref_sys;
-- 输出: 数千条
-- 查询特定坐标系
SELECT srid, auth_name, auth_srid, srtext
FROM spatial_ref_sys
WHERE srid IN (4326, 3857, 4490, 4547);
-- 添加自定义坐标系
INSERT INTO spatial_ref_sys (srid, auth_name, auth_srid, proj4text, srtext)
VALUES (
990001,
'CUSTOM',
990001,
'+proj=tmerc +lat_0=0 +lon_0=117 +k=1 +x_0=39500000 +y_0=0 +datum=WGS84 +units=m',
'PROJCS["Custom Transverse Mercator",GEOGCS["WGS 84",DATUM["WGS_84",...]]'
);
3.11 PostGIS 函数命名约定
PostGIS 遵循一致的命名约定,便于记忆和使用:
| 前缀 | 含义 | 示例 |
|---|---|---|
ST_ | Spatial Type (标准函数) | ST_Intersects, ST_Buffer |
ST_Geom | 几何创建/转换 | ST_GeomFromText, ST_GeomFromGeoJSON |
ST_As | 几何输出 | ST_AsText, ST_AsGeoJSON, ST_AsEWKB |
ST_Set | 设置属性 | ST_SetSRID |
ST_Is | 布尔判断 | ST_IsValid, ST_IsEmpty |
ST_Num | 数量统计 | ST_NumPoints, ST_NumGeometries |
3.12 本章小结
| 要点 | 说明 |
|---|---|
| 双类型系统 | Geometry(笛卡尔)vs Geography(球面) |
| 空间索引 | GiST 为主,SP-GiST 和 BRIN 为辅 |
| 坐标系统 | SRID 定义坐标系,PROJ 实现转换 |
| 核心引擎 | GEOS(几何)、PROJ(投影)、GDAL(栅格) |
| 元数据 | geometry_columns 视图和 spatial_ref_sys 表 |
| 命名约定 | ST_ 前缀统一所有空间函数 |