PostGIS是一个空间数据库,空间数据库像存储和操作数据库中其他任何对象一样去存储和操作空间对象。
空间数据库将空间数据和对象关系数据库(Object Relational database)完全集成在一起。实现从以GIS为中心向以数据库为中心的转变。
PostGIS通过向PostgreSQL添加对空间数据类型、**空间索引(R-Tree)和空间函数的支持,将PostgreSQL数据库管理系统转换为空间数据库**,可以说PostGIS仅仅只是PostgreSQL的一个插件,但是它将PostgreSQL变成了一个强大的空间数据库!
最重要的只要接触过SQL语言,就可以利用PostGIS的SQL语法便捷的操纵装载着空间信息的数据框(数据表),这些二维表除了被设定了一个特殊的空间地理信息字段(带有空间投影信息、经纬度信息等)之外,与主流数据管理系统所定义的各种字段并无两样。
PostGIS安装不仅依赖于PostgreSQL,还依赖于很多插件:
PostGIS的特点如下:
空间函数构建于SQL语言中,用于进行空间属性和空间关系的查询,空间函数中的大部分可以被归纳为以下五类:
参考: https://zhuanlan.zhihu.com/p/67232451
使用geography这种数据类型时,PostGIS的内部计算是基于实际地球球体来计算的;
而使用geometry这种数据类型时,PostGIS的内部计算是基于平面来计算的。
Geometry(几何对象类型)是PG的一个基本存储类型,PostGIS的空间数据都会以Geometry的形式存储在PostgreSQL里,本质是个二进制对象。
PostGIS基于OGC的“Simple Feature for Specification for SQL”规范,在Geometry对象上实现了一系列的GIS Object(地物对象),使用了OGC推荐的WKT(Well-Known Text)和WKB(Well-Known Binary)格式进行描述,大幅增加了易用性,例如WKT的7个基本类型:
点:POINT(0 0) 线:LINESTRING(0 0,1 1,1 2) 面(多边形):POLYGON((0 0,4 0,4 4,0 4,0 0)) 简单多边形 POLYGON((0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2, 1 2,1 1)) 多边形有一个内部的”孔洞(hole)” 多点:MULTIPOINT((0 0),(1 2)) 多线:MULTILINESTRING((0 0,1 1,1 2),(2 3,3 2,5 4)) 多面:MULTIPOLYGON(((0 0,4 0,4 4,0 4,0 0),(1 1,2 1,2 2,1 2,1 1)), ((-1 -1,-1 -2,-2 -2,-2 -1,-1 -1))) 几何集合:GEOMETRYCOLLECTION(POINT(2 3),LINESTRING(2 3,3 4))
PostGIS自身又在WKT和WKB基础上扩展实现了EWKT和EWKB来满足更复杂的场景需求,EWKT和EWKB相比OGC WKT和WKB格式主要的扩展有3DZ、3DM、4D坐标和内嵌空间参考支持。
SQL-MM格式定义了一些插值曲线,这些插值曲线和EWKT有点类似,也支持3DZ、3DM、4D坐标,但是不支持嵌入空间参考。
地理类型提供支持本地空间特性的“地理”坐标(有时称为“大地”坐标,或“纬度/经度”,或“经度/纬度”)。它的几何基础是球面。
计算两点间的距离相当于计算圆弧的距离,不能使用平面几何原理,需要通过其他参考方法计算。
由于底层算法复杂,定义的地理类型比空间类型少很多,随之算法的增加,将出现新的地理类型。
PostGresSQL8.3推出一张表辅助空间参考表:spatial_ref_sys表,它存放的是OGC规范的空间参考。辅助转化。
地理类型只支持简单的简单的元素。标准几何类型数据将自动转换到地理WGS84坐标。还可以使用EWKT和EWKB约定来插入数据。
patial_ref_sys表,它存放的是OGC规范的空间参考。我们取我们最熟悉的4326参考看一下:
它的srid存放的就是空间参考的Well-Known ID,对这个空间参考的定义主要包括两个字段,srtext存放的是以字符串描述的空间参考,proj4text存放的则是以字符串描述的PROJ.4 投影定义(PostGIS使用PROJ.4实现投影)
SRID 4326声明了地理空间参考系统
如下创建表:
CREATE TABLE global_points ( id SERIAL PRIMARY KEY, name VARCHAR(64), location GEOGRAPHY(POINT,4326) );
插入数据:
INSERT INTO global_points (name, location) VALUES (‘London’, ST_GeographyFromText(‘SRID=4326; POINT(-72.1235 42.3521)’));
PostGIS可以检查几何信息的正确性,这主要是通过IsValid函数实现的。 以下语句分辨检查了2个几何对象的正确性,显然,(0, 0)点和(1,1)点可以构成一条线,但是(0, 0)点和(0, 0)点则不能构成,这个语句执行以后的得出的结果是TRUE,FALSE。
select IsValid(‘LINESTRING(0 0, 1 1)’), IsValid(‘LINESTRING(0 0,0 0)’)
默认PostGIS并不会使用IsValid函数检查用户插入的新数据,因为这会消耗较多的CPU资源(特别是复杂的几何对象)。当你需要使用这个功能的时候,你可以使用以下语句为表新建一个检查约束:
ALTER TABLE cities ADD CONSTRAINT geometry_valid CHECK (IsValid(shape))
这时当我们往这个表试图插入一个错误的空间对象的时候,会得到一个错误:
INSERT INTO test.cities ( shape, name ) VALUES ( GeomFromText(‘LINESTRING(0 0,0 0)’, 4326), ‘北京’); ERROR: new row for relation “cities” violates check constraint “geometry_valid” SQL 状态: 23514
PS : geometry,是几何类型的列的列名
srid,不同的srid就是不同标准的坐标系
点空间函数:
线串空间函数:
多边形空间函数:
集合空间函数(多点、多线、多面、任意图形组合):
在数据库中,几何图形(Geometry)以仅供PostGIS使用的格式存储在磁盘上。为了让外部程序插入和检索有用的几何图形信息,需要将它们转换为其他应用程序可以理解的格式。
①Well-known text(WKT)
②Well-known binary(WKB)
③Geographic Mark-up Language(GML)
④Keyhole Mark-up Language(KML)
⑥Scalable Vector Graphics(SVG)
以上函数最常见的用法是将几何图形的文本(text)表示形式转换为内部表示形式
请注意,除了具有几何图形表示形式的文本参数外,还可以指定一个提供几何图形SRID的数字参数。
ST_Equals(geometry A, geometry B)
ST_Intersects、ST_Disjoint、ST_Crosses和ST_Overlaps
ST_Touches()
ST_Within和ST_Contains
ST_Distance和ST_DWithin
text
geography
bytea
geography
text
text
text
text
double
boolean
double
double
boolean
boolean
boolean
geography
[1]geography
[1]geography转换为geometry
PostgreSQL的类型转换语法是将 ::typename 附加到希望转换的值的末尾。因此,2::text将数字2转换为文本字符串”2″;‘POINT(0 0)’ :: geometry将点的文本表示形式转换为geometry点
空间连接(spatial joins)是空间数据库的主要组成部分,它们允许你使用空间关系作为连接键(join key)来连接来自不同数据表的信息,如:
SELECT subways.name AS subway_name, neighborhoods.name AS neighborhood_name, neighborhoods.boroname AS borough FROM nyc_neighborhoods AS neighborhoods JOIN nyc_subway_stations AS subways ON ST_Contains(neighborhoods.geom, subways.geom) WHERE subways.name = ‘Broad St’;
任何在两个表之间提供true/false关系的函数都可以用来驱动空间连接,但最常用的函数是:
ST_Intersects、ST_Contains和ST_DWithin
默认情况下,数据库使用的是INNER JOIN连接类型,还可以用 LEFT OUTER JOIN、RIGHT OUTER JOIN
如下创建一个空间索引:
CREATE INDEX nyc_census_blocks_geom_idx ON nyc_census_blocks USING GIST (geom)
USING GIST子句告诉PostgreSQL在构建索引时使用generic index structure(GIST-通用索引结构)
PostGIS使用”R-Tree“空间索引结构。R-Tree将数据分解为矩形(rectangle)、子矩形(sub-rectangle)和子-子矩形(sub-sub rectangle)等。它是一种可自动处理可变数据的密度和对象大小的自调优(self-tuning)索引结构。
对于一个大的数据表来说,先计算出近似结果,然后进行精确测试的”两遍”机制可以从根本上减少计算量。(这种思想就是粗调和精调的思想,就像显微镜一样有粗粒度的调整和细粒度的调整。很多事物都涉及到这个思想,它的作用就是减少了耗费的代价)
使用索引:
SELECT Sum(popn_total)FROM nyc_neighborhoods neighborhoodsJOIN nyc_census_blocks blocksON neighborhoods.geom && blocks.geomWHERE neighborhoods.name = ‘West Village’;
PostgreSQL查询规划器(query planner)智能地选择何时使用或不使用空间索引来计算查询。与直觉相反,执行空间索引搜索并不总是更快:如果搜索将返回表中的每条记录,则遍历索引树以获取每条记录实际上比从一开始线性读取整个表要慢(注意这句话)。
为了弄清楚要处理的数据的大概内容(读取表的一小部分信息,而不是读取表的大部分信息),PostgreSQL保存每个索引列中数据分布的统计信息。默认情况下,PostgreSQL定期收集统计信息。但是,如果你在短时间内更改了表的构成,则统计数据将不会是最新的。
为确保统计信息与表内容匹配,明智的做法是在表中加载和删除大容量数据后手动运行ANALYZE命令。这将强制统计系统收集所有索引列的统计信息。
ANALYZE命令要求PostgreSQL遍历该表并更新用于查询操作而估算的内部统计信息。
ANALYZE nyc_census_blocks;
值得强调的是,仅仅创建空间索引不足以让PostgreSQL有效地使用它。每当创建新索引或对表大量更新、插入或删除后,都必须执行清理(VACUUMing)。VACUUM命令要求PostgreSQL回收表页面中因记录的更新或删除而留下的任何未使用的空间。
清理对于数据库的高效运行非常关键,因此,PostgreSQL提供了一个“自动清理(autovacuum)”选项。
默认情况下,自动清理机制会根据活动级别确定的合理时间间隔自动清理(恢复空间)和分析(更新统计信息)。虽然这对于高度事务性的数据库是必不可少的功能,但在添加索引或大容量数据之后等待自动清理运行是不明智的,如果执行大批量更新,则应该手动运行VACUUM命令。
根据需要,可以单独执行清理和分析。发出VACUUM命令不会更新数据库统计信息;同样,执行ANALYZE命令也不会清理未使用的表空间。这两个命令都可以针对整个数据库、单个表或单个列运行。
VACUUM ANALYZE nyc_census_blocks;
**ST_Buffer(geometry, distance)**接受几何图形和缓冲区距离作为参数,并输出一个多边形,这个多边形的边界与输入的几何图形之间的距离与输入的缓冲区距离相等。
叠置(overlay)- 通过计算两个重叠多边形的交集来创建新的几何图形。
**ST_Intersection(geometry A, geometry B)**函数返回两个参数共有的空间区域(或直线,或点)。如果参数不相交,该函数将返回一个空几何图形
ST_Union将两个几何图形合并起来。ST_Union函数有两种形式
ALTER TABLE mytable ADD CONSTRAINT geometry_valid_check CHECK (ST_IsValid(the_geom));
单个点(Point)肯定是简单的且有效的,因为一个点孤零零的肯定是简单、有效的
多个点(MultiPoint)肯定是有效的,但不一定是简单的。
如果多点中有两个或两个以上的点重合(也就是坐标一致),那么它就不是简单的,但是确是有效的
单线串(LINESTRING)如果有重叠、相交就不是简单的(除了端点相交,端点相交就说明这条线串是闭合的,但它是简单的)
多线串(MULTILINESTRING)只要它的元素(LINESTRING)都是简单的,且两个元素只在某个点相切,那么它就是简单
有效性:
多边形的环只要不自相交,则该多边形就是简单的
多多边形里只要各个子元素(单多边形)是简单的、有效的,而且子元素之间只在有限的点上接触,那么它就是简单的、有效的。
精确相等是通过按顺序逐个比较两个几何图形的顶点来确定的,以确保它们在位置上是相同的。确定图形的点位置和顺序不同,则图形不等
精确的相等并没有考虑到几何图形的空间性质。有一个名为ST_Equals的函数,可用于测试几何图形的空间相等性或等价性。无论是绘制多边形的方向、定义多边形的起点,还是使用的点的个数的差异在这里都不重要。重要的是多边形包含相同的空间区域。图形的实际形状相同,则图形相等
在最坏的情况下,需要精确相等来比较几何图形中的每个顶点以确定相等。这可能会比较慢,并且可能不适合数量大的几何图形。为了更快地进行比较,提供了等边界运算符 ’ = ’ 。这仅在**边界框(矩形)**上操作,确保几何图形占用相同的二维范围,但不一定占用相同的空间。**边界框(矩形)**相同,则图形相等
执行最近邻域搜索的简单方法是按与要查询的几何图形的距离对候选表进行排序,然后获取最小距离对应的表记录
SELECT streets.gid, streets.nameFROM nyc_streets streets, nyc_subway_stations subwaysWHERE subways.name = ‘Broad St’ORDER BY ST_Distance(streets.geom, subways.geom) ASCLIMIT 1;
ST_MakeEmptyRaster用于创建一个空的没有像元值的栅格(没有波段),各个参数用于定义这个空栅格的元数据:
上面的第一个函数签名传入现有的栅格数据作为新创建栅格的模板,会返回具有相同元数据(没有波段、没有像元值)的栅格数据。
在创建了一个空栅格之后,要向其添加波段,并可能要对其进行编辑。可以使用以下函数:
ST_AsMVTGeom
将一个图层中位于参数box2d范围内的一个几何图形的所有坐标转换为MapBox VectorTile坐标空间里的坐标。
该函数会尽量保持、甚至纠正,来确保几何图形的有效性(有效性可以查看这篇文章:https://zhuanlan.zhihu.com/p/117267292),并可能在此过程中将几何图形降维(比如三维几何图形被处理成二维几何图形)。
函数各个参数的含义:
ST_AsMVT聚合函数用于将基于MapBox VectorTile坐标空间的几何图形转换为MapBox VectorTile二进制矢量切片。
PostGIS生成MVT矢量切片的步骤是:
MVT格式可以存储具有不同属性集的要素。要使用此功能,请在行数据中包含一个JSONB列,该列通过在一级深度下包含多个Json对象来存储多个不同属性集。JSONB中的键和值将被编码为要素属性。
可以通过”||“操作符调用多次这个函数来同时创建多个图层的同一位置的矢量切片。
**注意:**不要将GEOMETRYCOLLECTION类型的几何图形作为参数进行切片,但是可以使用ST_AsMVTGeom函数来准备GEOMETRYCOLLECTION类型的几何图形。
函数各个参数的含义: