GIS

PostGIS是什么

了解PostGIS的基本概念、核心能力、空间数据类型、空间函数、空间索引以及PostGIS在GIS和WebGIS中的应用。

阅读约 99 分钟

PostGIS是什么

PostGIS是PostgreSQL数据库的空间数据库扩展。

它为PostgreSQL增加了GIS空间数据存储、空间查询、空间分析和空间索引等能力。

普通数据库主要处理:

字符串
数字
日期
JSON
数组

安装PostGIS以后,PostgreSQL还可以处理:

Point
LineString
Polygon
MultiPolygon
Raster

并且可以执行:

距离计算
面积计算
空间相交
空间包含
缓冲区分析
坐标转换
空间索引

简单来说:

PostGIS就是让PostgreSQL具备专业GIS空间数据库能力的扩展。

PostgreSQL是什么

PostgreSQL是一种开源关系型数据库。

它可以存储:

用户
订单
商品
日志
业务数据

例如:

CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    name TEXT
);

数据库结构:

PostgreSQL
    ↓
Database
    ↓
Table
    ↓
Row
    ↓
Column

PostGIS则是在这个基础上增加空间数据能力。

PostGIS解决什么问题

传统数据库保存一个地点时,可能只保存:

longitude = 116.397
latitude = 39.908

这种方式只能简单保存坐标。

如果使用PostGIS,可以直接保存:

POINT (116.397 39.908)

并进行空间查询:

附近有哪些商店?
两个地点距离多远?
哪些道路与这个区域相交?
哪些建筑位于这个行政区?

因此:

普通数据库
    ↓
保存业务数据

PostGIS
    ↓
保存业务数据
+
空间数据
+
空间计算
+
空间查询

PostGIS的核心能力

PostGIS主要提供以下能力:

空间数据存储
空间数据查询
空间分析
空间关系判断
空间索引
坐标转换
GIS数据格式转换

可以理解为:

PostGIS
├── Spatial Data
├── Spatial Query
├── Spatial Analysis
├── Spatial Index
├── CRS
└── Data Conversion

PostGIS支持哪些空间数据

PostGIS最常见的空间数据类型包括:

Geometry
Geography
Raster

其中Geometry是最常用的矢量空间数据类型。

常见Geometry:

Point
MultiPoint
LineString
MultiLineString
Polygon
MultiPolygon
GeometryCollection

例如:

Point
    ↓
一个位置

LineString
    ↓
一条道路

Polygon
    ↓
一个区域

Geometry

Geometry是PostGIS中最核心的空间数据类型之一。

例如:

POINT (116.397 39.908)

可以存储到:

geometry(Point, 4326)

数据库字段:

CREATE TABLE cities (
    id SERIAL PRIMARY KEY,
    name TEXT,
    geom geometry(Point, 4326)
);

其中:

geom
 ↓
Geometry

Point
 ↓
空间类型

4326
 ↓
SRID

Geography

PostGIS还提供:

Geography

它主要用于基于地球曲面进行空间计算。

例如:

POINT(116.397 39.908)

可以使用:

geography(Point, 4326)

Geometry和Geography最大的区别可以简单理解为:

Geometry
 ↓
平面空间计算

Geography
 ↓
地球曲面上的地理计算

因此进行全球范围的距离、面积等计算时,Geography有时更加方便。

Raster

PostGIS还支持Raster空间数据。

Raster主要用于:

卫星影像
遥感数据
DEM
地形数据
栅格地图

可以理解为:

Vector
 ↓
Point
Line
Polygon

Raster
 ↓
Pixel
 ↓
Grid

因此PostGIS不仅可以存储矢量数据,也可以处理部分栅格数据。

SRID是什么

SRID用于表示空间数据使用的坐标参考系统。

例如:

EPSG:4326

和:

EPSG:3857

都是常见的空间参考系统。

例如:

geometry(Point, 4326)

表示:

Geometry
 ↓
Point
 ↓
SRID = 4326

SRID非常重要。

如果两个Geometry使用不同的坐标参考系统,就不能简单地直接进行某些空间计算。

EPSG:4326

EPSG:4326是非常常见的地理坐标参考系统。

通常使用:

经度
纬度

例如:

116.397
39.908

可以表示:

经度 = 116.397
纬度 = 39.908

在PostGIS中:

geometry(Point, 4326)

是非常常见的定义方式。

EPSG:3857

EPSG:3857是WebGIS中非常常见的投影坐标系。

很多Web地图使用:

EPSG:3857

例如:

OpenLayers
Leaflet
Web地图Tile

经常会使用Web Mercator投影。

因此WebGIS中经常出现:

EPSG:4326
    ↓
ST_Transform()
    ↓
EPSG:3857

ST_SetSRID与ST_Transform

PostGIS中非常重要的两个函数:

ST_SetSRID
ST_Transform

ST_SetSRID:

给Geometry设置SRID

例如:

SELECT ST_SetSRID(
    ST_Point(116.397, 39.908),
    4326
);

它不会真正改变坐标数值。

ST_Transform:

真正进行坐标转换

例如:

SELECT ST_Transform(
    geom,
    3857
)
FROM cities;

因此:

ST_SetSRID
 ↓
设置坐标参考信息

ST_Transform
 ↓
转换坐标

PostGIS空间函数

PostGIS最大的优势之一就是提供大量空间函数。

例如:

ST_Distance
ST_Length
ST_Area
ST_Buffer
ST_Intersects
ST_Contains
ST_Within
ST_Intersection
ST_Union
ST_Transform

这些函数可以直接在SQL中使用。

ST_Distance

用于计算两个Geometry之间的距离。

例如:

SELECT ST_Distance(
    a.geom,
    b.geom
)
FROM cities a, cities b;

可以用于:

  • 最近地点
  • 两地距离
  • 服务范围
  • 距离分析

ST_Length

用于计算LineString长度。

例如:

SELECT ST_Length(geom)
FROM roads;

可以用于:

  • 道路长度
  • 河流长度
  • 管线长度
  • GPS轨迹长度

需要注意:

计算结果的单位与Geometry使用的坐标系有关。

ST_Area

用于计算Polygon面积。

例如:

SELECT ST_Area(geom)
FROM parcels;

可以用于:

  • 地块面积
  • 行政区面积
  • 建筑面积
  • 土地面积

同样需要注意坐标系和单位。

ST_Buffer

ST_Buffer用于创建缓冲区。

例如:

SELECT ST_Buffer(
    geom,
    100
)
FROM roads;

可以理解为:

道路
 ↓
100单位缓冲
 ↓
缓冲区域

常见应用:

  • 道路影响范围
  • 服务区分析
  • 环境影响分析
  • 安全距离
  • 周边设施查询

ST_Intersects

用于判断两个Geometry是否相交。

例如:

SELECT ST_Intersects(
    a.geom,
    b.geom
)
FROM roads a, parcels b;

返回:

true

或者:

false

典型问题:

哪些道路经过这个地块?

就可以使用空间相交查询。

ST_Contains

用于判断一个Geometry是否包含另一个Geometry。

例如:

SELECT ST_Contains(
    district.geom,
    city.geom
)
FROM districts district, cities city;

典型问题:

这个城市属于哪个行政区?

可以通过空间包含关系进行判断。

ST_Within

ST_Within与ST_Contains存在相反方向的关系。

例如:

城市
 ↓
Within
 ↓
行政区

SQL:

SELECT ST_Within(
    city.geom,
    district.geom
);

可以判断:

city是否位于district内部

ST_Intersection

ST_Intersection用于计算两个Geometry的交集。

例如:

Polygon A
      +
Polygon B
      ↓
Intersection
      ↓
交集区域

SQL:

SELECT ST_Intersection(
    a.geom,
    b.geom
)
FROM a, b;

常用于:

  • 行政区裁剪
  • 道路与区域分析
  • 土地重叠分析
  • 空间叠加

ST_Union

ST_Union用于合并Geometry。

例如:

Polygon A
+
Polygon B
 ↓
Union
 ↓
新的Geometry

SQL:

SELECT ST_Union(geom)
FROM parcels;

常用于:

  • 区域合并
  • 行政区合并
  • 地块融合
  • 空间数据聚合

空间索引

如果数据库中只有几十条空间数据:

100条

直接计算可能问题不大。

但如果有:

100万
1000万

个Geometry,就需要空间索引。

PostGIS常见空间索引:

GiST

例如:

CREATE INDEX idx_cities_geom
ON cities
USING GIST (geom);

这样数据库就可以利用空间索引进行高效空间查询。

为什么需要空间索引

假设有:

100万家商店

现在查询:

某个位置附近的商店。

没有空间索引:

100万
 ↓
逐个计算距离

有空间索引:

100万
 ↓
空间索引筛选
 ↓
少量候选对象
 ↓
精确计算

因此:

PostGIS
+
GiST
=
高效空间查询

PostGIS与WKT

WKT是一种空间数据文本格式。

例如:

POINT (116.397 39.908)

PostGIS可以使用:

ST_GeomFromText()

将WKT转换为Geometry。

例如:

SELECT ST_GeomFromText(
    'POINT (116.397 39.908)',
    4326
);

反向可以使用:

SELECT ST_AsText(geom)
FROM cities;

因此:

WKT
 ↓
ST_GeomFromText
 ↓
Geometry

以及:

Geometry
 ↓
ST_AsText
 ↓
WKT

PostGIS与WKB

WKB是Geometry的二进制表示方式。

PostGIS可以使用:

ST_AsBinary()

输出WKB。

例如:

SELECT ST_AsBinary(geom)
FROM cities;

也可以使用:

ST_GeomFromWKB()

将WKB转换为Geometry。

因此:

WKT
 ↓
文本

WKB
 ↓
二进制

Geometry
 ↓
PostGIS空间对象

PostGIS与GeoJSON

PostGIS可以直接生成GeoJSON。

例如:

SELECT ST_AsGeoJSON(geom)
FROM cities;

得到:

{
  "type": "Point",
  "coordinates": [116.397, 39.908]
}

也可以将GeoJSON转换为Geometry:

SELECT ST_GeomFromGeoJSON(
    '{"type":"Point","coordinates":[116.397,39.908]}'
);

因此PostGIS非常适合WebGIS后端。

PostGIS与Shapefile

Shapefile是传统GIS中非常常见的数据格式。

可以通过GIS工具将:

Shapefile
 ↓
PostGIS

导入数据库。

例如:

.shp
.shx
.dbf
.prj

共同组成Shapefile数据集。

导入PostGIS以后,可以进行:

空间查询
空间分析
空间索引
数据更新
WebGIS服务

因此PostGIS经常作为Shapefile数据的数据库存储目标。

PostGIS与GeoPackage

GeoPackage是一种基于SQLite的GIS数据格式。

可以理解为:

GeoPackage
 ↓
SQLite
 ↓
GIS空间数据

而PostGIS:

PostGIS
 ↓
PostgreSQL
 ↓
GIS空间数据库

两者都可以存储:

Geometry
Attributes
Spatial Reference

但PostGIS更适合:

服务器
多人访问
大型空间数据库
WebGIS
空间查询
空间分析

PostGIS与GeoParquet

GeoParquet是一种面向分析场景的空间数据格式。

可以理解为:

GeoParquet
 ↓
Parquet
 ↓
列式存储
 ↓
空间数据

而PostGIS更加偏向:

数据库
 ↓
事务
 ↓
查询
 ↓
空间索引
 ↓
空间分析

两者可以配合使用。

例如:

PostGIS
 ↓
分析
 ↓
GeoParquet
 ↓
数据交换 / 大数据分析

PostGIS与WebGIS

PostGIS非常适合用于WebGIS后端。

典型架构:

                    浏览器
                       ↓
              OpenLayers / Leaflet
                       ↓
                      API
                       ↓
                 后端服务
                       ↓
                    PostGIS
                       ↓
                 PostgreSQL

例如用户在地图上点击一个区域:

用户点击地图
    ↓
发送坐标
    ↓
API
    ↓
PostGIS
    ↓
空间查询
    ↓
返回GeoJSON
    ↓
前端显示

PostGIS典型应用

PostGIS可以用于很多GIS业务。

地图服务

地图
 ↓
空间数据
 ↓
PostGIS

LBS

用户位置
 ↓
附近商店
附近医院
附近停车场

路网分析

道路
 ↓
距离
路径
连通性

城市规划

地块
建筑
道路
行政区

物流

车辆
仓库
配送点
道路

资产管理

设备
管线
建筑
设施

环境分析

河流
污染源
保护区
土地

一个简单的PostGIS示例

创建扩展:

CREATE EXTENSION postgis;

创建城市表:

CREATE TABLE cities (
    id SERIAL PRIMARY KEY,
    name TEXT,
    geom geometry(Point, 4326)
);

插入数据:

INSERT INTO cities (name, geom)
VALUES (
    '北京',
    ST_SetSRID(
        ST_Point(116.397, 39.908),
        4326
    )
);

查询WKT:

SELECT
    name,
    ST_AsText(geom)
FROM cities;

结果:

北京
POINT(116.397 39.908)

输出GeoJSON:

SELECT
    name,
    ST_AsGeoJSON(geom)
FROM cities;

创建空间索引:

CREATE INDEX idx_cities_geom
ON cities
USING GIST (geom);

这就是一个最基本的PostGIS空间数据流程。

PostGIS完整数据流程

一个典型的GIS数据进入PostGIS的过程:

Shapefile
GeoJSON
WKT
CSV
GeoPackage
    ↓
数据导入
    ↓
PostGIS
    ↓
Geometry
    ↓
SRID
    ↓
空间索引
    ↓
空间查询
    ↓
空间分析
    ↓
GeoJSON
    ↓
WebGIS

PostGIS数据架构

可以从三个层次理解PostGIS:

PostgreSQL
    ↓
数据库能力
    │
    ├── Table
    ├── SQL
    ├── Transaction
    └── Index
         ↓
PostGIS
    ↓
空间能力
    │
    ├── Geometry
    ├── Geography
    ├── Spatial Function
    ├── Spatial Index
    └── CRS
         ↓
GIS应用
    │
    ├── WebGIS
    ├── LBS
    ├── 地图服务
    ├── 空间分析
    └── 数据管理

PostGIS与普通数据库的区别

能力PostgreSQLPostgreSQL + PostGIS
普通数据支持支持
JSON支持支持
Geometry不属于核心能力支持
Geography不支持支持
空间索引不支持支持
空间距离不支持支持
空间相交不支持支持
空间缓冲不支持支持
坐标转换不支持支持
GIS分析有限强大

因此:

PostGIS不是一个独立的数据库,而是PostgreSQL的GIS空间扩展。

PostGIS与传统GIS软件

传统GIS软件:

QGIS
ArcGIS

更偏向:

桌面GIS
地图制作
数据编辑
空间分析

PostGIS更偏向:

空间数据库
数据存储
空间查询
多人访问
WebGIS后端
服务端空间分析

实际项目中经常组合使用:

QGIS
 ↓
编辑GIS数据
 ↓
PostGIS
 ↓
保存空间数据
 ↓
WebGIS
 ↓
OpenLayers

PostGIS知识结构

可以这样理解:

PostGIS
├── PostgreSQL
│
├── Spatial Data
│   ├── Geometry
│   ├── Geography
│   └── Raster
│
├── CRS
│   ├── EPSG:4326
│   └── EPSG:3857
│
├── Spatial Functions
│   ├── Distance
│   ├── Length
│   ├── Area
│   ├── Buffer
│   ├── Intersection
│   ├── Union
│   └── Spatial Relations
│
├── Spatial Index
│   └── GiST
│
├── Data Formats
│   ├── WKT
│   ├── WKB
│   ├── GeoJSON
│   ├── Shapefile
│   └── GeoPackage
│
└── Applications
    ├── WebGIS
    ├── LBS
    ├── 地图服务
    └── 空间分析

PostGIS与GIS知识体系

PostGIS在整个GIS知识体系中可以放在:

GIS
│
├── 数据
│   ├── Vector
│   ├── Raster
│   └── Tile
│
├── 数据格式
│   ├── Shapefile
│   ├── GeoJSON
│   ├── WKT
│   ├── WKB
│   ├── GeoPackage
│   └── GeoParquet
│
├── 坐标系统
│   ├── CRS
│   ├── EPSG:4326
│   └── EPSG:3857
│
├── 空间分析
│   ├── Buffer
│   ├── Distance
│   ├── Intersection
│   └── Spatial Relation
│
└── 空间数据库
    └── PostGIS

总结

PostGIS是PostgreSQL的空间数据库扩展。

它让PostgreSQL能够直接存储和处理GIS空间数据。

核心能力包括:

Geometry
Geography
Raster
CRS
空间函数
空间索引

可以进行:

距离计算
长度计算
面积计算
缓冲区分析
相交分析
包含判断
空间集合运算
坐标转换

同时可以与:

WKT
WKB
GeoJSON
Shapefile
GeoPackage
GeoParquet

等GIS数据格式进行数据交换。

在WebGIS中,一个典型架构是:

PostGIS
    ↓
空间查询
    ↓
API
    ↓
GeoJSON
    ↓
OpenLayers / Leaflet
    ↓
地图

最终可以记住:

PostGIS = PostgreSQL + GIS空间数据 + 空间索引 + 空间查询 + 空间分析。

🧰

相关工具

使用 IYATools 在线工具快速处理 GIS 数据