云数据库 PostgreSQL postgis

这篇说说腾讯云PostgreSQL中postgis空间地理信息插件的功能、安装、空间表创建、距离查询、空间索引、关系判断及子扩展(sfcgal、topology、raster)的使用方法。 – 核心功能:提供几何类型、空间函数与GiST索引,支持球面距离、范围查询、最近邻查询及坐标转换。 – 子扩展:postgis_sfcgal(三维几何)、postgis_topology(拓扑管理)、postgis_raster(。

相关产品
云数据库 PostgreSQL 产品页,含版本规格、价格与购买入口。

这里说明 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 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 | 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 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 判断两条三维线段是否相交。

20、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')。

21、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 判断栅格与几何是否相交。

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

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

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

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

25、相关参考

postgis 产品文档

赞 (0)
上一篇 4天前
下一篇 4天前