帮你快速理解、总结文档立即下载

postgis

最近更新时间:2026-09-16 11:44:01
我的收藏
本文为您介绍 postgis 插件的简介及使用方法。

概述

postgis 是空间地理信息插件,提供几何类型、空间函数和空间索引,支持距离计算、范围查询、空间关系判断、几何运算、坐标转换等能力,并提供拓扑、栅格、三维几何等子扩展,适用于地图、位置服务、地理信息系统等场景。

支持版本

PostgreSQL 版本
内核版本
PostgreSQL 10
v10.23_r1.21及以上
PostgreSQL 11
v11.22_r1.40及以上
PostgreSQL 12
v12.22_r1.42及以上
PostgreSQL 13
v13.22_r1.37及以上
PostgreSQL 14
v14.23_r1.46及以上
PostgreSQL 15
v15.18_r1.33及以上
PostgreSQL 16
v16.14_r1.28及以上
PostgreSQL 17
v17.10_r1.21及以上
PostgreSQL 18
v18.4_r1.12及以上
说明:
您可在控制台实例详情页查看当前实例的内核版本,或执行 SHOW tencentdb_version; 查询。

插件简介

postgis 由一个主扩展和多个可选子扩展组成:
扩展
功能
postgis
空间类型、空间函数、空间索引(本文档主要内容)
postgis_sfcgal
三维几何运算(挤出、体积、三维相交等)
postgis_topology
拓扑数据管理
postgis_raster
栅格数据存储与分析

环境准备

在目标数据库中执行以下语句创建主扩展:
postgres=> CREATE EXTENSION postgis;
CREATE EXTENSION
说明:
postgis 无需预加载,创建后即可使用空间类型和函数。子扩展按需创建,用法见 子扩展 章节。

创建空间表与插入数据

geometry(Point, 4326) 表示 WGS84坐标系(经纬度)下的点类型。以下示例创建空间表并插入城市坐标:
postgres=> CREATE TABLE places (
id int,
name text,
geom geometry(Point, 4326)
);
CREATE TABLE
postgres=> INSERT INTO places VALUES
(1, 'Beijing', ST_GeomFromText('POINT(116.4 39.9)', 4326)),
(2, 'Shanghai', ST_GeomFromText('POINT(121.5 31.2)', 4326)),
(3, 'Guangzhou', ST_GeomFromText('POINT(113.3 23.1)', 4326));
INSERT 0 3
postgres=> SELECT id, name, ST_AsText(geom) AS geom FROM places ORDER BY id;
id | name | geom
----+-----------+-------------------
1 | Beijing | POINT(116.4 39.9)
2 | Shanghai | POINT(121.5 31.2)
3 | Guangzhou | POINT(113.3 23.1)
(3 rows)
说明:
ST_GeomFromText 用于从 WKT(Well-Known Text)文本构造几何对象,ST_AsText 将几何对象转换为 WKT 文本。

空间距离查询

球面距离

使用 ST_DistanceSphere 计算两点之间的球面距离(单位:米):
postgres=> SELECT round(ST_DistanceSphere(
(SELECT geom FROM places WHERE name='Beijing'),
(SELECT geom FROM places WHERE name='Shanghai'))::numeric, 0) AS distance_m;
distance_m
------------
1071287
(1 row)
说明:
北京到上海的球面距离约为1071公里。

范围内查询

使用 ST_DWithin 查询指定范围内的对象。以下示例查找距离北京1100公里以内的城市:
postgres=> SELECT name FROM places
WHERE ST_DWithin(geom::geography, (SELECT geom FROM places WHERE name='Beijing')::geography, 1100000)
AND name <> 'Beijing';
name
----------
Shanghai
(1 row)
说明:
ST_DWithin 的第三个参数为距离(单位:米)。::geography 将几何类型转换为地理类型,使其按球面距离计算。

空间索引与最近邻查询

创建空间索引

为空间列创建 GiST 索引,加速空间查询:
postgres=> CREATE INDEX places_geom_idx ON places USING gist (geom);
CREATE INDEX

最近邻查询

使用 <-> 操作符按距离排序,查询最近的相邻对象。先补充更多城市数据:
postgres=> INSERT INTO places VALUES
(4, 'Shenzhen', ST_GeomFromText('POINT(114.1 22.5)', 4326)),
(5, 'Hangzhou', ST_GeomFromText('POINT(120.2 30.3)', 4326)),
(6, 'Chengdu', ST_GeomFromText('POINT(104.1 30.6)', 4326)),
(7, 'Wuhan', ST_GeomFromText('POINT(114.3 30.6)', 4326)),
(8, 'Xian', ST_GeomFromText('POINT(108.9 34.3)', 4326));
INSERT 0 5
postgres=> SELECT name, round(ST_DistanceSphere(geom, (SELECT geom FROM places WHERE name='Shanghai'))::numeric, 0) AS dist_m
FROM places WHERE name <> 'Shanghai'
ORDER BY geom <-> (SELECT geom FROM places WHERE name='Shanghai') LIMIT 3;
name | dist_m
----------+---------
Hangzhou | 159523
Wuhan | 690078
Beijing | 1071287
(3 rows)
说明:
ORDER BY geom <-> ... 使用空间索引进行最近邻查询,返回距离上海最近的3个城市,其中杭州距离约159公里。

空间关系判断

使用 ST_Contains 判断几何对象是否包含另一个对象。以下示例判断城市是否位于华东区域(约东经115 - 125、北纬25 - 40)内:
postgres=> SELECT ST_Contains(
ST_GeomFromText('POLYGON((115 25, 125 25, 125 40, 115 40, 115 25))', 4326),
(SELECT geom FROM places WHERE name='Shanghai')
) AS shanghai_in_area;
shanghai_in_area
------------------
t
(1 row)
postgres=> SELECT ST_Contains(
ST_GeomFromText('POLYGON((115 25, 125 25, 125 40, 115 40, 115 25))', 4326),
(SELECT geom FROM places WHERE name='Chengdu')
) AS chengdu_in_area;
chengdu_in_area
-----------------
f
(1 row)
说明:
上海位于华东区域多边形内返回 t,成都位于区域外返回 f

更多几何运算

线长度与面面积

ST_Length 配合 geography 类型计算线路的实际长度(单位:米):
postgres=> SELECT round(ST_Length(ST_GeomFromText('LINESTRING(116.4 39.9, 117.2 39.1, 118.8 37.4, 120.3 36.1, 121.5 31.2)', 4326)::geography)::numeric, 0) AS line_length_m;
line_length_m
---------------
1098957
(1 row)
说明:
上述京沪沿线折线的球面长度约为1099公里。
ST_Area 配合 geography 类型计算多边形的实际面积(单位:平方米):
postgres=> SELECT round(ST_Area(ST_GeomFromText('POLYGON((115 25, 125 25, 125 40, 115 40, 115 25))', 4326)::geography)::numeric, 0) AS area_m2;
area_m2
----------------
1559310606085
(1 row)
说明:
上述华东区域多边形的面积约为156万平方公里。

缓冲区与质心

ST_Buffer 生成几何对象周边的缓冲区:
postgres=> SELECT ST_GeometryType(ST_Buffer(ST_GeomFromText('POINT(116.4 39.9)', 4326), 5)) AS buffer_type, ST_NPoints(ST_Buffer(ST_GeomFromText('POINT(116.4 39.9)', 4326), 5)) AS num_points;
buffer_type | num_points
---------------+------------
ST_Polygon | 33
(1 row)
说明:
ST_Buffer 以点为中心、5度为半径生成多边形缓冲区(33个顶点)。
ST_Centroid 计算几何对象的质心:
postgres=> SELECT ST_AsText(ST_Centroid(ST_GeomFromText('POLYGON((115 25, 125 25, 125 40, 115 40, 115 25))', 4326))) AS centroid;
centroid
---------------
POINT(120 32.5)
(1 row)

坐标转换

ST_Transform 在不同坐标系之间转换坐标。以下示例将 WGS84(4326)坐标转换为 Web Mercator(3857):
postgres=> SELECT ST_AsText(ST_Transform(ST_GeomFromText('POINT(116.4 39.9)', 4326), 3857)) AS web_mercator;
web_mercator
---------------------------------------------
POINT(12957588.728337044 4851421.175183359)
(1 row)

GeoJSON 输出

ST_AsGeoJSON 将几何对象输出为 GeoJSON 格式,便于与前端地图组件交互:
postgres=> SELECT ST_AsGeoJSON(ST_GeomFromText('POINT(116.4 39.9)', 4326)) AS geojson;
geojson
-------------------------------------------
{"type":"Point","coordinates":[116.4,39.9]}
(1 row)

子扩展

postgis_sfcgal(三维几何)

提供三维几何运算能力,如挤出、体积计算、三维相交判断:
postgres=> CREATE EXTENSION postgis_sfcgal;
CREATE EXTENSION
postgres=> SELECT round(ST_Volume(ST_MakeSolid(ST_Extrude(ST_GeomFromText('POLYGON((0 0, 1 0, 1 1, 0 0))'), 0, 0, 1)))::numeric, 2) AS volume;
volume
--------
0.50
(1 row)
postgres=> SELECT ST_3DIntersects(
ST_GeomFromText('LINESTRING Z(0 0 0, 0 0 1)'),
ST_GeomFromText('LINESTRING Z(0 0 0.5, 0 0 2)')
) AS intersects_3d;
intersects_3d
---------------
t
(1 row)
说明:
ST_Extrude 将平面三角形沿 Z 轴挤出1个单位,ST_Volume 计算挤出后的三维实体体积(面积0.5 × 高度1 = 0.50);ST_3DIntersects 判断两条三维线段是否相交。

postgis_topology(拓扑)

提供拓扑数据管理能力,用于维护共享边界的空间数据(如行政区、地籍)。以下示例创建拓扑并向表添加拓扑几何列:
postgres=> CREATE EXTENSION postgis_topology;
CREATE EXTENSION
postgres=> SELECT CreateTopology('demo_topo', 4326);
createtopology
----------------
1
(1 row)
postgres=> CREATE TABLE land_parcels (id int, name text);
CREATE TABLE
postgres=> SELECT AddTopoGeometryColumn('demo_topo', 'public', 'land_parcels', 'topo_geom', 'polygon');
addtopogeometrycolumn
----------------------
1
(1 row)
postgres=> SELECT * FROM topology.topology WHERE name = 'demo_topo';
id | name | srid | precision | hasz
----+-----------+------+-----------+------
1 | demo_topo | 4326 | 0 | f
(1 row)
说明:
CreateTopology 创建一个独立的拓扑(生成同名 schema,内含 node、edge、face 等表),AddTopoGeometryColumn 将拓扑管理的几何列添加到业务表。清理拓扑时使用 DropTopology('demo_topo')

postgis_raster(栅格)

提供栅格数据类型与分析能力。以下示例将面几何转换为栅格并查询栅格属性:
postgres=> CREATE EXTENSION postgis_raster;
CREATE EXTENSION
postgres=> CREATE TABLE rasters (id int, rast raster);
CREATE TABLE
postgres=> INSERT INTO rasters VALUES
(1, ST_AsRaster(ST_GeomFromText('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))'), 100, 100, '8BUI', 128));
INSERT 0 1
postgres=> SELECT id, ST_Width(rast) AS width, ST_Height(rast) AS height, ST_NumBands(rast) AS bands FROM rasters;
id | width | height | bands
----+-------+--------+-------
1 | 100 | 100 | 1
(1 row)
postgres=> SELECT ST_Value(rast, 1, 50, 50) AS pixel_value FROM rasters WHERE id = 1;
pixel_value
-------------
128
(1 row)
postgres=> SELECT ST_Intersects(rast, ST_GeomFromText('POINT(5 5)')) AS point_intersects FROM rasters WHERE id = 1;
point_intersects
------------------
t
(1 row)
说明:
ST_AsRaster 将10 × 10的面转换为100 × 100像素的8位无符号整型栅格(初始值128),ST_Value 取指定像素的值,ST_Intersects 判断栅格与几何是否相交。

常见问题

Q:创建扩展后需要加载其他子扩展吗?

A:postgis 提供多个可选子扩展(如 postgis_topologypostgis_rasterpostgis_sfcgal),按需创建即可。基础的点线面几何、距离计算、空间索引等功能包含在主扩展 postgis 中。

Q:删除 postgis 时提示有依赖对象?

A:请先删除依赖 postgis 的子扩展和对象(如 DROP EXTENSION postgis_sfcgal CASCADE;),再删除主扩展;创建过拓扑的,需先调用 DropTopology 清理拓扑。

相关参考