强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

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 椭球体)
  • 单位始终为
  • 仅支持有限的几何操作
  • 计算较慢(需椭球体计算)
  • 适合大范围距离/面积计算

对比表

特性GeometryGeography
坐标系笛卡尔平面球面椭球体
距离单位取决于 SRID始终为米
支持的 SRID任意仅 4326 (WGS84)
空间索引GiSTGiST
可用函数全部 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名称类型覆盖范围常用场景
4326WGS 84地理坐标全球GPS 数据、Web 地图
3857Web Mercator投影坐标全球Web 地图瓦片
4490CGCS 2000地理坐标中国国内测绘标准
4547CGCS 2000 / 3-degree GK zone 39投影坐标中国 117°带国内工程测量
32650WGS 84 / UTM zone 50N投影坐标东经 114°-120°中国东部沿海
2154RGF93 / 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_ 前缀统一所有空间函数

扩展阅读