版本:8.0.25(推荐版本:≥8.24)
MySQL空间扩展支持产生、存储和分析地理元素。
- 数据类型用于表示空间值。
- 函数用于操作空间值。
- 空间索引用于提高空间列的访问速度。
MySQL数据类型和函数支持MyISAM、InnoDB、NDB和Archive表。MyISAM和InnoDB支持SPATIAL和no-SPATIAL索引。其他引擎只支持no-SPATIAL索引。由于InnoDB是默认存储引擎,应采用InnoDB存储空间数据。
空间数据类型
//参考:《refman-8.0-en.pdf》11.4空间数据类型。//
几何类型
类型 | 名称 | 备注 |
geometry | 几何 | 储存点、线、面、多点、多线、多面 |
geometrycollection | 几何集合 | 支持储存任意几何的集合 |
point | 点 | |
linestring | 线 | |
polygon | 面 | |
multipoint | 多点 | |
multilinestring | 多线 | |
multipolygon | 多面 |
示例:
create table geom (g geometry);
create table geom (
p point srid 0,
g geometry not null srid 4326
);
SRID表示空间参考系(SRS):例如:4326、3857
创建空间索引要求列:NOT NULL,并且有一个SRID。例如:
create table geom (g geometry not null srid 4326);
InnoDB表支持SRID值为笛卡尔和地理坐标系,MyISAM表限制SRID值为笛卡尔坐标系。
SRID属性对列的限制:
- 仅支持存储指定的SRID数据。
- 优化器可以在列上使用空间索引。
对于不加SRID属性的列:
- 没有SRID限制。
- 优化器不能创建空间索引。
层级结构
Geometry(不能实例化)
Point(可以实例化)
Curve(不能实例化)
LineString(可以实例化)
Line
LinearRing
Surface(不能实例化)
Polygon(可以实例化)
GeometryCollection(可以实例化)
MultiPoint(可以实例化)
MultiCurve(不能实例化)
MultiLinearString(可以实例化)
MultiSurface(不能实例化)
MultiPolygon(可以实例化)
Geometry类
Geometry属性:type, SRID, coordinates, interior, boundary, exterior, MBR(最小包围盒)或envelope。
SRID默认值为0,表示一个无限平坦的笛卡尔平面,坐标轴没有单位。计算时必须采用相同的SRID。
MBR格式:((minx miny, maxx miny, maxx maxy, minx maxy, minx miny))
分类:
- 简单或非简单:线、多点、多线。
- 闭合或非闭合:线、多线。
- 空或非空:
维度:-1表示空几何,0表示几何没有长度和面积,1表示有长度没面积,2表示有长度有面积。
Point类
Point属性:X、Y。
一个点是一个零维几何,范围是空集。
Curve类
曲线属性:一些点的坐标。
曲线是一维几何。
简单曲线:简单曲线不能通过一个点两次;但是开始点和结束点可以相同。
闭合曲线:曲线开始点和结束点相同。
闭合曲线的范围是空的。
非闭合曲线范围是两个端点。
一条曲线如果它既是简单的又是闭合的,那么它是一个LinearRing。
LineString类
LineString是一个曲线,它在点之间是线性插值的。
LineString属性:点的坐标。
LineString变成Line,如果它只有两个点。
LineString变成LineRing,如果它既闭合又简单。
Surface类
Surface是二维几何,不可实例化。
Surface属性:OpenGIS规范定义Surface是包含一个patch的几何,它关联了一个闭合区域和0个或多个内部边界。
一个简单Surface的范围是闭合曲线的外部或内部边界。
Polygon类
一个Polygon是一个平面,它有一个外部边界和0个或多个内部边界,内部边界表示面上的孔。
简单Polygon:
- Polygon边界包括一些线圈,这些线圈组成了它的外部和内部边界。
- Polygon不能包含相交的圈。Polygon边界上的圈可以相交于一点,但是只能作为切线。
- Polygon不能有线、尖刺或小孔。
- Polygon可以有一些点组成的内部。
- Polygon可以有空。一个有孔的外部边界不是连接的。
GeometryCollection类
MultiPoint类
MultiCurve类
MultiLineString类
MultiSurface类
MultiPolygon类
支持的空间数据类型
WKT格式
WKB格式
MySQL存储几何类似WKB,但是起始4个字节表示SRID。
SKT格式
一个点:POINT(15 20)
一条线:LINESTRING(0 0, 10 10, 20 25, 50 60)
一个面包括一个空:POLYGON((0 0, 10 0, 10 10, 10 0, 0 0), (5 5, 7 5, 7 7, 5 7, 5 5))
一个多点:MULTIPOINT(0 0, 20 20, 60 60)
一个多线:MULTILINESTRING((10 10, 20 20), (15 15, 30 15))
一个多面:MULTIPOLYGON~(~(~(0 0, 10 0, 10 10, 0 10, 0 0)), ((5 5, 7 5, 7 7, 5 7, 5 5~)~)~)
一个几何集合:GEOMETRYCOLLECTION(POINT(10 10), POINT(30 30), LINESTRING(15 15, 20 20))
示例1:SELECT ST_X(POINT(15, 20));;
示例2:SELECT ST_X(ST_GeomFromText(‘POINT(15, 20)’));
示例3:ST_MPointFromText(‘MULTIPOINT(1 1, 2 2, 3 3)’);
示例4:ST_MPointFromText(MULTIPOINT( (1 1), (2 2), ( 3 3 ) ));
WKB格式
组成:字节序(1比特)、WKB类型(4比特)、x坐标(8比特)、Y坐标(8比特)
内部储存类型
4比特SRID+WKB格式。
- 字节序是1,因为MySQL储存几何是小端字节序。
- 支持几何类型:Point,LineString,Polygon,MultiPoint,MultiLineString,MultiPolygon,GeometryCollection。
- 只有GeometryCollection允许为空。
- 面中的空支持顺时针和逆时针,读取数据时MySQL会自动翻转。
- 笛卡尔坐标:长度单位保存在空间参考系,X值保存在X,Y值保存在Y,坐标轴方向保存在空间参考系。
- 地理坐标:角度单位保存在空间坐标系,经度保存在X,纬度保存在Y,坐标轴方向保存在空间参考系。
LENGTH返回保存所需比特数。
示例:
SET @g = ST_GeomFromText(‘POINT(1 -1)’);
SELECT LENGTH(@g);
SELECT HEX(@g);
几何结构良好性和有效性
结构良好的:
- 线至少2个点。
- 面至少1个圈。
- 面圈是闭合的。
- 面圈至少4个点,第一个点和第四个点是相同的。
- 几何非空。(除了GeometryCollection)
有效的:
- 面不能跟自己相交。
- 面内部的圈在外部圈的内部。
- 多面不能有重叠的面。
判断几何是否有效:ST_IsValid函数
空间参考系支持
投影坐标系:
地理坐标系:
坐标系表在数据字典:mysql.st_spatial_reference_systems表,它是不可见的,可以通过INFORMATION_SCHEMA ST_SPATIAL_REFERENCE_SYSTEMS视图查询。
示例:SELECT * FROM INFORMATION_SCHEMA.ST_SPATIAL_REFERENCE_SYSTEMS WHERE SRS_ID=4326;
创建空间列
示例1:CREATE TABLE geom (g GEOMETRY);
示例2:ALTER TABLE geom ADD pt POINT;
示例3:ALTER TABLE geom DROP pt;
填充空间列
示例1:
INSERT INTO geom VALUES (ST_GeomFromText(‘POINT(1 1)’));
SET @g = ‘POINT(1 1)’;
INSERT INTO geom VALUES (ST_GeomFromText(@g));
示例2:
SET @g = ST_GeomFromText(‘POINT(1 1)’);
INSERT INTO geom VALUES (@g);
示例3:
SET @g = ‘LINESTRING(0 0, 1 1, 2 2)’;
INSERT INTO geom VALUES (ST_GeomFromText(@g));
SET @g = ‘POLYGON((0 0, 10 0, 10 10, 0 10, 0 0), (5 5, 7 5, 7 7, 5 7, 5 5))’;
INSERT INTO geom VALUES (ST_GeomFromText(@g));
SET @g=’GEOMETRYCOLLECTION(POINT(1 1), LINESTRING(0 0, 1 1, 2 2, 3 3, 4 4))’;
INSERT INTO geom VALUES (ST_GeomFromText(@g));
示例4:
SET @g = ‘POINT(1 1)’;
INSERT INTO geom VALUES (ST_PointFromText(@g));
SET @g = ‘LINESTRING(0 0, 1 1, 2 2)’;
INSERT INTO geom VALUES (ST_LineStringFROMText(@g));
SET @g = ‘POLYGON((0,0, 10 0, 10 10, 0 10, 0 0), (5 5, 7 5, 7 7, 5 7, 5 5))’;
INSERT INTO geom VALUES (ST_PolygonFromText(@g));
SET @g = ‘GEOMETRYCOLLECTION(POINT(1 1), LINESTRING(0 0, 1 1, 2 2, 3 3, 4 4))’;
INSERT INTO geom VALUES (ST_GeomCollFromText(@g));
获取空间数据
示例1:
CREATE TABLE geom2 (g GEOMETRY) SELECT g FROM geom;
示例2:
SELECT ST_AsText(g) FROM geom;
SELECT ST_AsBinary(g) FROM geom;
优化空间分析
MySQL使用二次方分裂R树来为空间列创建空间索引。
创建空间索引
示例1:
CREATE TABLE geom (g GEOMETRY NOT NULL SRID 4326, SPATIAL INDEX(g));
示例2:
CREATE TABLE geom (g GEOMETRY NOT NULL SRID 4326);
ALTER TABLE geom ADD SPATIAL INDEX(g);
示例3:
CREATE TABLE geom (g GEOMETRY NOT NULL SRID 4326);
CREATE SPATIAL INDEX g ON geom (g);
示例4:
ALTER TABLE geom DROP INDEX g;
示例5:
DROP INDEX g ON geom;
空间索引:R树,非空间索引:B树。
示例6:
DESCRIBE geom;
使用空间索引
示例1(查询多边形内元素):
SET @poly = ‘Polygon((30000 15000, 31000 15000, 31000 16000, 30000 16000, 30000 15000))’;
SELECT fid,ST_AsText(g) FROM geom WHERE MBRContains(ST_GeomFromText(@poly), g);
示例2(解析查询执行):
SET @poly = ‘Polygon((30000 15000, 31000 15000, 31000 16000, 30000 16000, 30000 15000))’;
EXPLAIN SELECT fid,ST_AsText(g) FROM geom WHERE MBRContains(ST_GeomFromText(@poly), g);
空间分析函数
//参考:《refman-8.0-en.pdf》12.17空间分析函数。//
名称 | 简介 |
GeomCollection() | 通过几何构建几何集合 |
GeometryCollection() | 通过几何构建几何集合 |
LineString() | 通过点值创建LineString |
MBRContains() | 一个几何包围盒是否包含另一个 |
MBRCoveredBy() | 一个几何包围盒是否被另一个包含 |
MBRCovers() | 一个几何包围盒是否包含另一个 |
MBRDisjoint() | 两个几何包围盒是否不相交 |
MBREquals() | 两个几何包围盒是否相等 |
MBRIntersects() | 两个几何包围盒是否相交 |
MBROverlaps() | 两个几何包围盒是否重叠 |
MBRTouches() | 两个几何包围盒是否接触 |
MBRWithin() | 一个几何包围盒是否在另一个中间 |
MultiLineString() | 使用LineString构建一个MultiLineString |
MultiPoint() | 通过Point创建MultiPoint |
MultiPolygon() | 通过Polygon创建MultiPolygon |
Point() | 通过坐标创建一个点 |
Polygon() | 通过LineString创建一个Polygon |
ST_Area() | 返回Polygon或MultiPolygon的面积 |
ST_AsBinary(),ST_AsWKB() | 将内部类型转为WKB |
ST_AsGeoJSON() | 通过几何产生GeoJSON对象 |
ST_AsText(),ST_AsWKT() | 将内部几何转换为WKT |
ST_Buffer() | 返回离几何一定距离的一些点 |
ST_Buffer_Strategy() | 为ST_Buffer()创建策略。 |
ST_Centroid() | 返回几何中心 |
ST_Collect() | 聚合空间值为几何(8.0.24后支持) |
ST_Contains() | 一个几何是否包含另一个 |
ST_ConvexHull() | 返回几何凸包 |
ST_Crosses() | 一个几何是否穿过另一个 |
ST_Difference() | 返回两个几何差异的点集 |
ST_Dimension() | 几何纬度 |
ST_Disjoint() | 一个几何是否与另一个不相连 |
ST_Distance() | 一个几何到另一个的距离 |
ST_Distance_Sphere() | 地面上两个几何的最近距离 |
ST_EndPoint() | LineString的终点 |
ST_Envelope() | 返回几何最小包围盒 |
ST_Equals() | 两个几何是否相同 |
ST_ExteriorRing() | 范围Polygon的外部圈 |
ST_FrechetDistance() | 返回两个几何的弗雷歇距离(8.0.23后支持) |
ST_GeoHash() | 产生地理哈希值 |
((( |
ST_GeomCollFromText(),
ST_GeometryCollectionFromText(),
ST_GeomCollFromTxt()
)))|通过WKT返回几何集合
((( |
ST_GeomCollFromWKB(),
ST_GeometryCollectionFromWKB()
)))|通过WKB返回几何几何
ST_GeometryN() | 返回几何集合上的第n个几何 |
ST_GeometryType() | 返回几何类型的名称 |
ST_GeomFromGeoJSON() | 通过GeoJSON产生几何 |
((( |
ST_GeomFromText(),
ST_GeometryFromText()
)))|通过WKT产生几何
((( |
ST_GeomFromWKB(),
ST_GeometryFromWKB()
)))|通过WKB产生几何
ST_HausdorffDistance() | 两个几何之间的豪斯多夫距离(8.0.23后支持) |
ST_InteriorRingN() | 返回Polygon的第n个孔 |
ST_Intersection() | 返回两个几何相交的点集 |
ST_Intersects() | 一个几何与另一个是否相交 |
ST_IsClosed() | 一个几何是否闭合而且简单 |
ST_IsEmpty() | 一个几何是否是空集 |
ST_IsSimple() | 一个几何是否简单 |
ST_IsValid() | 一个几何是否有效 |
ST_LatFromGeoHash() | 从地理哈希值获取纬度 |
ST_Latitude() | 返回点的纬度 |
ST_Length() | 返回线的长度 |
((( |
ST_LineFromText(),
ST_LineStringFromText()
)))|通过WKT创建LineString
((( |
ST_LineFromWKB(),
ST_LineStringFromWKB()
)))|通过WKB创建线
ST_LineInterpolatePoint() | 沿LineString给定百分比的点(8.0.24后支持) |
ST_LineInterpolatePoints() | 沿LineString给定百分比的点集(8.0.24后支持) |
ST_LongFromGeoHash() | 返回地理哈希值的经度 |
ST_Longitude() | 返回点的经度(8.0.12后支持) |
ST_MakeEnvelope() | 通过两个点创建信封 |
((( |
ST_MLineFromText(),
ST_MultiLineStringFromText()
)))|通过WKT创建多线
((( |
ST_MLineFromWKB(),
ST_MultiLineStringFromWKB()
)))|通过WKB创建多线
((( |
ST_MPointFromText(),
ST_MultiPointFromText()
)))|通过WKT创建多点
((( |
ST_MPointFromWKB(),
ST_MultiPointFromWKB()
)))|通过WKB创建多点
((( |
ST_MPolyFromText(),
ST_MultiPolygonFromText()
)))|通过WKT创建多面
((( |
ST_MPolyFromWKB(),
ST_MultiPolygonFromWKB()
)))|通过WKB创建多面
ST_NumGeometries() | 返回几何集合中几何的数量 |
((( |
ST_NumInteriorRing(),
ST_NumInteriorRings()
)))|返回面中孔的数量
ST_NumPoints() | 返回线中孔的数量 |
ST_Overlaps() | 一个几何是否与另一个重写 |
ST_PointAtDistance() | 沿着LineString给定距离的点(8.0.24后支持) |
ST_PointFromGeoHash() | 计算点的地理哈希值 |
ST_PointFromText() | 通过WKT创建点 |
ST_PointFromWKB() | 通过WKB创建点 |
ST_PointN() | 返回线的第n个点 |
((( |
ST_PolyFromText(),
ST_PolygonFromText()
)))|通过WKT创建面
((( |
ST_PolyFromWKB(),
ST_PolygonFromWKB()
)))|通过WKB创建面
ST_Simplify() | 简化几何 |
ST_SRID() | 返回几何的SRID |
ST_StartPoint() | 返回线的起始点 |
ST_SwapXY() | 返回x和y交换的值 |
ST_SymDifference() | 返回两个几何对称不同的点集 |
ST_Touches() | 两个几何是否接触 |
ST_Transform() | 转换几何坐标(8.0.13) |
ST_Union() | 返回两个几何合并后的点集 |
ST_Validate() | 判断几何是否有效 |
ST_Within() | 一个几何是否在另一个几何内部 |
ST_X() | 返回点的X值 |
ST_Y() | 返回点的Y值 |
几何格式转换
//参考:《refman-8.0-en.pdf》12.17.6几何格式转换函数。//
空间索引
//参考:《refman-8.0-en.pdf》8.3.3空间索引优化。//
//参考:《refman-8.0-en.pdf》13.1.15创建索引。//
空间参考系表
//参考:《refman-8.0-en.pdf》13.1.19创建空间参考系。//
//参考:《refman-8.0-en.pdf》13.1.31删除空间参考系。//
//参考:《refman-8.0-en.pdf》26.3.36空间索引优化。//
INFORMATION_SCHEMA ST_SPATIAL_REFERENCE_SYSTEMS表。