本文为您介绍 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
说明:
创建空间表与插入数据
geometry(Point, 4326) 表示 WGS84坐标系(经纬度)下的点类型。以下示例创建空间表并插入城市坐标:postgres=> CREATE TABLE places (id int,name text,geom geometry(Point, 4326));CREATE TABLEpostgres=> 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 3postgres=> 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 placesWHERE 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 5postgres=> SELECT name, round(ST_DistanceSphere(geom, (SELECT geom FROM places WHERE name='Shanghai'))::numeric, 0) AS dist_mFROM places WHERE name <> 'Shanghai'ORDER BY geom <-> (SELECT geom FROM places WHERE name='Shanghai') LIMIT 3;name | dist_m----------+---------Hangzhou | 159523Wuhan | 690078Beijing | 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 EXTENSIONpostgres=> 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 EXTENSIONpostgres=> SELECT CreateTopology('demo_topo', 4326);createtopology----------------1(1 row)postgres=> CREATE TABLE land_parcels (id int, name text);CREATE TABLEpostgres=> 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 EXTENSIONpostgres=> CREATE TABLE rasters (id int, rast raster);CREATE TABLEpostgres=> 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 1postgres=> 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_topology、postgis_raster、postgis_sfcgal),按需创建即可。基础的点线面几何、距离计算、空间索引等功能包含在主扩展 postgis 中。Q:删除 postgis 时提示有依赖对象?
A:请先删除依赖 postgis 的子扩展和对象(如
DROP EXTENSION postgis_sfcgal CASCADE;),再删除主扩展;创建过拓扑的,需先调用 DropTopology 清理拓扑。