MySQL 数据类型:空间数据类型

来自Wikioe
跳到导航 跳到搜索


关于空间数据类型

MySQL 空间扩展可实现地理 Feature 的生成,存储和分析:

  1. 表示空间值的数据类型
  2. 操纵空间值的功能
  3. 空间索引可缩短对空间列的访问时间
  • 空间数据类型和功能可用于 MyISAMInnoDBNDBARCHIVE 表。对于空间列的索引,MyISAM 和 InnoDB 支持 SPATIAL非SPATIAL 索引。【???】


地理 Feature 是世界上任何具有位置的东西。功能可以是:

  1. 一个实体。例如,山,池塘,城市。
  2. 空间。例如,市区,热带地点。
  3. 可定义的位置。例如,十字路口,作为两条街道相交的特定位置。

空间数据类型

MySQL 具有与 OpenGIS 类相对应的空间数据类型。【???】


一些空间数据类型保存单个几何值:

  1. GEOMETRY【几何】
  2. POINT【点】
  3. LINESTRING【线】
  4. POLYGON【多边形】
  • GEOMETRY 可以存储任何类型的几何值。其他单值类型(POINT,LINESTRING 和 POLYGON)将其值限制为特定的几何类型。


其他空间数据类型包含值的集合:

  1. MULTIPOINT【多点】
  2. MULTILINESTRING【多线】
  3. MULTIPOLYGON【多边形集】
  4. GEOMETRYCOLLECTION
  • GEOMETRYCOLLECTION 可以存储任何类型的对象的集合。其他集合类型(MULTIPOINT,MULTILINESTRING 和 MULTIPOLYGON)将集合成员限制为具有特定几何类型的成员。


示例:要创建一个名为geom的 table,该 table 具有一个名为g的列,该列可以存储任何几何类型的值,请使用以下语句:

CREATE TABLE geom (g GEOMETRY);
  • 可以在 NOT NULL 空间列上创建 SPATIAL 索引,因此,如果您打算为该列构建索引,请声明NOT NULL:
    CREATE TABLE geom (g GEOMETRY NOT NULL);
    

OpenGIS 几何模型

OGC 的“SQL with Geometry Types”环境提出的几何类型集基于 OpenGIS Geometry Model 。在此模型中,每个几何对象都具有以下常规属性:

  1. 它与空间参考系统相关联,该系统描述了在其中定义对象的坐标空间。
  2. 它属于某些几何类。


GEOMETRY 类的层次结构:

  • Geometry(不可实例化)
  • Point(可实例)
  • Curve(不可实例化)
    • LineString(可实例)
      • Line
      • LinearRing(可实例)
  • Surface(不可实例化)
    • Polygon(可实例)
  • GeometryCollection(可实例)
  • MultiPoint(可实例)
  • MultiCurve(不可实例化)
    • MultiLineString(可实例)
  • MultiSurface(不可实例化)
    • MultiPolygon(可实例)

Geometry 是基础类。这是一个抽象类。 Geometry 的可实例化子类被限制为存在于二维坐标空间中的零、一和二维几何对象。

基本 Geometry 类具有 Point,Curve,Surface 和 GeometryCollection 的子类:

  1. Point 代表零维对象。
  2. Curve 代表一维对象,并具有子类别 LineString,以及子子类别 Line 和LinearRing 。
  3. Surface 是为二维对象设计的,具有子类 Polygon。
  4. GeometryCollection 具有名为 MultiPoint,MultiLineString 和 MultiPolygon 的专用零维,一维和二维收集类,用于分别建模与 Points,LineStrings 和 Polygons 的集合对应的几何形状。 MultiCurve 和 MultiSurface 作为抽象超类引入,它们泛化了收集接口以处理 Curves 和 Surfaces。
  • Geometry,Curve,Surface,MultiCurve 和 MultiSurface 被定义为非实例类。它们为其子类定义了一组通用的方法,并且为了扩展性而将它们包括在内。
  • Point,LineString,Polygon,GeometryCollection,MultiPoint,MultiLineString 和 MultiPolygon 是可实例化的类。

GEOMETRY 类

Geometry是层次结构的根类。它是一个不可实例化的类,但具有以下列表中描述的许多属性,这些属性对于从任何 Geometry子类创建的所有几何值都是共有的。(特定的子类具有自己的特定属性)

Geometry 属性:

  1. 它的 类型 。每个几何都属于层次结构中的可实例化类之一。
  2. SRID空间参考标识符。该值标识与几何相关的空间参考系统,该系统描述了在其中定义几何对象的坐标空间。
    在 MySQL 中,SRID 值是与几何值关联的整数。可用的最大 SRID 值为 232-1【???】。如果给出较大的值,则仅使用较低的 32 位。不管实际 SRID 值如何,所有计算均假设 SRID 为 0。 SRID 0 表示无限平坦的笛卡尔平面,其轴未分配任何单位。
  3. 它在空间参考系统中的“坐标”,表示为双精度(8 字节)数字。所有非空几何均包括至少一对“(X,Y)”坐标。空几何不包含坐标。
    坐标与 SRID 相关。例如,在不同的坐标系中,即使对象具有相同的坐标,两个对象之间的距离也可能会有所不同,这是因为 平面 坐标系上的距离和 大地坐标 坐标系上的距离(地球表面)是不同的东西。
  4. 它的“内部”,“边界”和“外部”。
    每个几何都在空间中占据某些位置。几何图形的外部是几何图形未占用的所有空间。内部是几何所占据的空间。边界是几何图形的内部和外部之间的接口。
  5. MBR(最小边界矩形)或包络。这是由最小和最大“(X,Y)”坐标形成的边界几何:
    ((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))
    
  6. 该值是 simple 还是 nonsimple 。类型(LineString,MultiPoint,MultiLineString)的几何值可以是简单的或不简单的。每种类型自己确定其值的简单或非简单。【???】
  7. 该值是 closed 还是 notclosed 。类型(LineString,MultiString)的几何值已关闭或未关闭。每种类型自己确定其值的关闭或未关闭。
  8. 值是 还是 非空。如果几何没有任何点,则为空。未定义空几何的外部,内部和边界(即,它们由“NULL”值表示)。空几何定义为始终简单,面积为 0。
  9. 尺寸 。几何的尺寸可以为 -1、0、1 或 2:
    1. -1 为空的几何。【空几何】
    2. 0 用于没有长度和面积的几何。【点、点集】
    3. 1 用于非零长度和零面积的几何。【线、线集】
    4. 2 用于非零面积的几何。【几何】
    • Point 对象的尺寸为零。 LineString 对象的尺寸为 1。Polygon对象的尺寸为 2。MultiPoint,MultiLineString 和 MultiPolygon 对象的尺寸与其组成的元素的尺寸相同。

Point 类

Point 是代表坐标空间中单个位置的几何。

Point示例:

  1. 想象一下有许多城市的大型世界地图。 Point 对象可以代表每个城市。
  2. 在城市地图上,Point 对象可以代表公交车站。

Point属性:

  1. X:坐标值。
  2. Y:坐标值。
  3. Point 被定义为零维几何。
  4. Point 的边界是空集。

Curve 类

Curve 是一维几何,通常由一系列点表示。 Curve的特定子类定义了点之间的插值类型。Curve是不可实例化的类。

Curve 属性:

  1. Curve具有其点的坐标。
  2. Curve被定义为一维几何。
  3. Curve如果不两次通过同一点,则很简单,不同之处是,如果起点和终点相同,则曲线仍可以是简单的。
  4. 如果 Curve 的起点等于端点,则为闭合。
  5. 闭合的 Curve 的边界为空。
  6. 未封闭的 Curve 的边界由其两个端点组成。
  7. 简单且封闭的Curve是 LinearRing。【环线】

LineString 类

LineString 是一种作为两点间直线插值的 Curve。

LineString 示例:

  1. 在世界地图上,LineString 个对象可以代表河流。
  2. 在城市地图中,LineString 个对象可以代表街道。

LineString 属性:

  1. LineString 具有段的坐标,由每个连续的点对定义。
  2. 如果 LineString 正好由两点组成,则它是 Line。【线段?】
  3. 如果 LineString 是封闭且简单的,则它是 LinearRing。【环线】

Surface 类

Surface是二维几何。这是一个不可实例化的类。它唯一的可实例化子类是 Polygon

Surface 属性:

  1. Surface 被定义为二维几何。
  2. OpenGIS 规范将简单的 Surface 定义为一种几何形状,它由与单个外部边界和零个或多个内部边界相关联的单个“补丁”组成。
  3. 简单Surface的边界是与其外部和内部边界相对应的一组闭合曲线。

Polygon 类

Polygon 是代表多边几何图形的平面 Surface。它由单个外部边界和零个或多个内部边界定义,其中每个内部边界在 Polygon 中定义一个孔【???hole】。

Polygon 示例:
在区域地图上,Polygon 对象可以代表森林,地点等。

Polygon 属性:

  1. Polygon 的边界由一组 LinearRing 对象(即简单且闭合的 LineString 对象)组成,这些对象组成其外部和内部边界。
  2. Polygon 没有交叉的环。 Polygon 边界中的环可在 Point 处相交,但仅作为切线。
  3. Polygon 没有线条,尖峰 或 刺孔。
  4. Polygon 的内部是连接的点集。
  5. Polygon 可能有孔。有孔(hole)的 Polygon 的外部是未连接在一起的。每个孔都定义了外部的连接组件。

GeometryCollection 类

GeometryCollection 是一个几何,它是零个或多个任何类的几何的集合

几何图形集合中的所有元素必须位于相同的空间参考系统(即,位于相同的坐标系)中。尽管以下各节中描述的 GeometryCollection 的子类可能会限制成员资格,但是几何集合的元素没有其他限制。限制可能基于:

  1. 元素类型(例如 MultiPoint 只能包含 Point 元素)
  2. 尺寸
  3. 限制元素之间的空间重叠程度

MultiPoint 类

MultiPoint 是由 Point 元素组成的几何集合。这些点没有以任何方式连接或排序。

MultiPoint 示例:

  1. 在世界地图上,MultiPoint 可以代表一连串的小岛。
  2. 在城市地图上,MultiPoint 可以代表售票处的网点。

MultiPoint 属性:

  1. MultiPoint 是零维几何。
  2. 如果 MultiPoint 的 Point 值中没有两个相等(具有相同的坐标值),则很简单。
  3. MultiPoint 的边界是空集。

MultiCurve 类

MultiCurve是由Curve个元素组成的几何集合。 MultiCurve是不可实例化的类。

MultiCurve 属性:

  1. MultiCurve 是一维几何。
  2. MultiCurve 仅当其所有元素都简单时才简单;两个元素之间唯一的交点出现在两个元素边界上的点处。
  3. 通过应用“mod 2 联合规则”(也称为“奇偶规则”)获得 MultiCurve 边界:如果某个点位于奇数个Curve元素的边界中,则该点位于MultiCurve的边界中。【???】
  4. 如果 MultiCurve 的所有元素都关闭,则关闭。
  5. 闭合的 MultiCurve 的边界始终为空。

MultiLineString 类

MultiLineString 是由 LineString 元素组成的 MultiCurve 几何图形集合。

MultiLineString 示例:
在区域 Map 上,MultiLineString可以代 table 河流系统或高速公路系统。

MultiSurface 类

MultiSurface是由 surface 元素组成的几何集合。 MultiSurface 是不可实例化的类。它唯一可实例化的子类是 MultiPolygon

MultiSurface 属性:

  1. MultiSurface 内的面不相交。
  2. MultiSurface 内的曲面最多具有有限个点的相交。【而非相交于面】

MultiPolygon 类

MultiPolygon 是由 Polygon 元素组成的 MultiSurface 对象。

MultiPolygon 示例:

  1. 在区域地图上,MultiPolygon 可以代表湖泊系统。

MultiPolygon 规则:

  1. MultiPolygon 没有两个 Polygon 元素的内部相交。
  2. MultiPolygon 没有两个 Polygon 元素交叉(上一个属性也禁止交叉)或在无数个点处接触。
  3. MultiPolygon 可能没有割线,尖峰或刺孔。 MultiPolygon 是常规的封闭点集。
  4. 具有多个 Polygon 的 MultiPolygon 内部没有连接。 MultiPolygon 内部的连接组件的数量等于 MultiPolygon 中的 Polygon 值的数量。

MultiPolygon 属性:

  1. MultiPolygon 是二维几何。
  2. MultiPolygon 边界是一组与其 Polygon 元素的边界相对应的闭合曲线(LineString值)。
  3. MultiPolygon 边界中的每个 Curve 都恰好在一个 Polygon 元素的边界中。
  4. Polygon 元素边界中的每个 Curve 都位于 MultiPolygon 的边界中。

支持的空间数据格式

两种标准空间数据格式用于表示查询中的几何对象:

  1. Literals(WKT)格式
  2. 二进制(WKB)格式
  • 在内部,MySQL 以不同于 WKT 或 WKB 的格式存储几何值。(类似于 WKB,但以 4 个初始字节表示 SRID)


WKT

【WKT 旨在用于交换 ASCII 形式的几何数据。】

WKT 几何对象 table 示的示例:

  1. 一个 Point:
    POINT(15 20)
    
    • 指定的点坐标不带逗号。【不同于SQL的“Point()”函数,该函数的坐标间需要逗号】例如,以下语句都使用ST_X()从Point对象提取 X 坐标:第一个直接使用“Point()”函数生成对象。第二种使用 WKT 表示形式,将“ST_GeomFromText()”转换为Point。
      mysql> SELECT ST_X(Point(15, 20));
      +---------------------+
      | ST_X(POINT(15, 20)) |
      +---------------------+
      |                  15 |
      +---------------------+
      
      mysql> SELECT ST_X(ST_GeomFromText('POINT(15 20)'));
      +---------------------------------------+
      | ST_X(ST_GeomFromText('POINT(15 20)')) |
      +---------------------------------------+
      |                                    15 |
      +---------------------------------------+
      
  2. 具有四个点的 LineString:
    LINESTRING(0 0, 10 10, 20 25, 50 60)
    
    • 点坐标对以逗号分隔。
  3. 具有一个外环和一个内环的 Polygon:
    POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))
    
  4. 具有三个 Point 值的 MultiPoint:
    MULTIPOINT(0 0, 20 20, 60 60)
    
    • 从 MySQL 5.7.9 开始,接受 MultiPoint 值的 WKT 格式表示的空间函数(例如ST_MPointFromText()和ST_GeomFromText())允许值内的各个点用括号括起来。例如,以下两个函数调用均有效:
      ST_MPointFromText('MULTIPOINT (1 1, 2 2, 3 3)')
      ST_MPointFromText('MULTIPOINT ((1 1), (2 2), (3 3))')
      
    • 从 MySQL 5.7.9 开始,MultiPoint 值的输出在每个点周围都包含括号。例如:
      mysql> SET @mp = 'MULTIPOINT(1 1, 2 2, 3 3)';
      mysql> SELECT ST_AsText(ST_GeomFromText(@mp));
      +---------------------------------+
      | ST_AsText(ST_GeomFromText(@mp)) |
      +---------------------------------+
      | MULTIPOINT((1 1),(2 2),(3 3))   |
      +---------------------------------+
      
    • 在 MySQL 5.7.9 之前,相同值的输出在每个点周围不包含括号:
      mysql> SET @mp = 'MULTIPOINT(1 1, 2 2, 3 3)';
      mysql> SELECT ST_AsText(ST_GeomFromText(@mp));
      +---------------------------------+
      | ST_AsText(ST_GeomFromText(@mp)) |
      +---------------------------------+
      | MULTIPOINT(1 1,2 2,3 3)         |
      +---------------------------------+
      
  5. 具有两个 LineString 值的 MultiLineString:
    MULTILINESTRING((10 10, 20 20), (15 15, 30 15))
    
  6. 具有两个 Polygon 值的 MultiPolygon:
    MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0)),((5 5,7 5,7 7,5 7, 5 5)))
    
  7. GeometryCollection 由两个 Point 值和一个 LineString 组成:
    GEOMETRYCOLLECTION(POINT(10 10), POINT(30 30), LINESTRING(15 15, 20 20))
    

WKB【???】

WKB 表示用于交换几何数据,作为由包含几何 WKB 信息的 BLOB 值表示的二进制流。【???】

WKB 使用 1 字节无符号整数,4 字节无符号整数和 8 字节双精度数字(IEEE 754 格式)。


示例: 例如,对应于“POINT(1 -1)”的 WKB 值由 21 个字节的序列组成,每个字节由两个十六进制数字表示:

0101000000000000000000F03F000000000000F0BF

其中:

组成部分 大小  说明
字节顺序 1 byte 01 该值为 1 或 0 分别表示小端或大端存储。小字节序和大字节序分别也称为网络数据表示(NDR)和外部数据表示示(XDR)。
WKB 类型 4 bytes 01000000 MySQL 使用从 1 到 7 的值来表示 Point,LineString,Polygon,MultiPoint,MultiLineString,MultiPolygon 和 GeometryCollection。
X 坐标 8 bytes 000000000000F03F 坐标都表示为双精度值
Y 坐标 8 bytes 000000000000F0BF

内部格式

MySQL 使用 4 个字节存储几何值,以指示 SRID,后跟该值的 WKB 表示。


对于 WKB 部分,这些特定于 MySQL 的注意事项适用:

  1. 字节顺序指示符字节为 1,因为 MySQL 将几何存储为低端值。
  2. MySQL 支持 Point,LineString,Polygon,MultiPoint,MultiLineString,MultiPolygon 和 GeometryCollection 的几何类型。不支持其他几何类型。


示例,“LENGTH()”函数返回值存储所需的字节空间:

mysql> SET @g = ST_GeomFromText('POINT(1 -1)');
mysql> SELECT LENGTH(@g);
+------------+
| LENGTH(@g) |
+------------+
|         25 |
+------------+
mysql> SELECT HEX(@g);
+----------------------------------------------------+
| HEX(@g)                                            |
+----------------------------------------------------+
| 000000000101000000000000000000F03F000000000000F0BF |
+----------------------------------------------------+

其中,值的长度是 25 个字节,由以下部分组成(从十六进制值可以看出):

  1. 4 个字节,用于整数 SRID(0)
  2. 1 个字节,表示整数字节顺序(1 =小字节序)
  3. 4 个字节,用于整数类型信息(1 = Point)
  4. 8 个双精度 X 坐标字节(1)
  5. 8 个双精度 Y 坐标的字节(-1)

几何格式正确性和有效性

对于几何值,MySQL 区分语法结构正确和几何有效的概念。

语法结构正确:

  1. 线串至少有两点
  2. 多边形至少有一个环
  3. 多边形环是闭合的(第一个点和最后一个点相同)
  4. 多边形环至少具有 4 个点(最小多边形是第一个点和最后一个点相同的三角形)
  5. 集合不为空(GeometryCollection除外)

几何有效:

  1. 多边形不是自相交的
  2. 多边形内圈位于外圈内
  3. 多边形不具有重叠的多边形
  • 如果几何结构的语法不正确,则空间功能将失败。解析 WKT 或 WKB 值的空间导入函数会因尝试创建语法上格式不正确的几何而产生错误。还检查语法格式正确性,以尝试将几何存储到 table 中。
  • 允许插入,选择和更新几何无效的几何,但是它们在语法上必须格式正确。由于计算量大,MySQL 不会明确检查几何有效性。空间计算可能会检测到无效几何的某些情况并引发错误,但它们也可能会返回未定义的结果而不会检测到无效性。需要几何有效几何形状的应用程序应使用“ST_IsValid()”功能对其进行检查。

创建空间列

MySQL 提供了一种用于为几何类型创建空间列的标准方法,例如,使用“CREATE TABLE”或“ALTER TABLE”。

  • MyISAM,InnoDB,NDB 和 ARCHIVE 的 table 支持空间列。
  1. 使用CREATE TABLE语句创建一个带有空间列的 table:
    CREATE TABLE geom (g GEOMETRY);
    
  2. 使用ALTER TABLE语句向现有 table 中添加或删除空间列:
    ALTER TABLE geom ADD pt POINT;
    ALTER TABLE geom DROP pt;
    

填充空间列

创建空间列之后,可以使用空间数据填充它们。

  • 值应以内部几何格式存储,但是可以将其从“已知文本”(WKT)或“已知二进制”(WKB)格式转换为该格式。


示例:通过将 WKT 值转换为内部几何格式将几何值插入 table 中:【使用“ST_GeomFromText()”创建几何值】

  1. 直接在 INSERT 语句中执行转换:
    INSERT INTO geom VALUES (ST_GeomFromText('POINT(1 1)'));
    
    SET @g = 'POINT(1 1)';
    INSERT INTO geom VALUES (ST_GeomFromText(@g));
    
  2. 在INSERT之前执行转换:
    SET @g = ST_GeomFromText('POINT(1 1)');
    INSERT INTO geom VALUES (@g);
    
  3. 以下示例将更复杂的几何插入 table 中:
    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));
    


前面的示例使用“ST_GeomFromText()”创建几何值。您还可以使用特定于类型的功能:【如:“ST_PointFromText()”、“ST_LineStringFromText()”、“ST_PolygonFromText()”、“ST_GeomCollFromText()”等】

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));


想要使用几何值的 WKB 表示形式的 Client 端应用程序负责将查询中正确形成的 WKB 发送到服务器。有几种方法可以满足此要求。例如:【使用“ST_GeomFromWKB()”】

  1. 使用十六进制 Literals 语法插入“POINT(1 1)”值:
    INSERT INTO geom VALUES
    (ST_GeomFromWKB(X'0101000000000000000000F03F000000000000F03F'));
    
  2. ODBC 应用程序可以发送 WKB 表示形式,并使用BLOB类型的参数将其绑定到占位符:
    INSERT INTO geom VALUES (ST_GeomFromWKB(?))
    
    • 其他编程接口可能支持类似的占位符机制。
    • 在 C 程序中,可以使用“mysql_real_escape_string_quote()”转义二进制值,并将结果包含在发送到服务器的查询字符串中。【???】

提取空间数据

可以以内部格式获取存储在 table 中的几何值。您也可以将它们转换为 WKT 或 WKB 格式。

  1. 以内部格式获取空间数据:
    • (使用内部格式获取几何值在 table 到 table 的传输中非常有用)
    CREATE TABLE geom2 (g GEOMETRY) SELECT g FROM geom;
    
  2. 以 WKT 格式获取空间数据:
    • ST_AsText()函数将几何图形从内部格式转换为 WKT 字符串。
    SELECT ST_AsText(g) FROM geom;
    
  3. 以 WKB 格式获取空间数据:
    • ST_AsBinary()函数将几何图形从内部格式转换为包含 WKB 值的BLOB。
    SELECT ST_AsBinary(g) FROM geom;
    

优化空间分析 【???】

对于 MyISAM 和 InnoDB 的表,可以使用SPATIAL 索引优化包含空间数据的列中的搜索操作。最典型的操作是:

  1. 点查询,搜索包含给定点的所有对象
  2. 区域查询搜索与给定区域重叠的所有对象


MySQL 对空间列上的 SPATIAL 索引使用“具有二次分裂的 R 树”【???】。使用几何的最小边界矩形(MBR)构建SPATIAL索引。对于大多数几何图形,MBR 是围绕几何图形的最小矩形。对于水平或垂直线串,MBR 是退化为线串的矩形。对于一个点,MBR 是退化为该点的矩形。

  • 也可以在空间列上创建普通索引。在非SPATIAL索引中,必须为除 POINT 列之外的任何空间列声明前缀。
  • MyISAM 和 InnoDB 支持 SPATIAL 和 非SPATIAL 索引。

创建空间索引

对于 InnoDB 和 MyISAM 数据表,MySQL 可以使用类似于创建常规索引的语法创建空间索引,但是使用SPATIAL关键字空间索引中的列必须声明为NOT NULL。 (“SPATIAL”:空间的)


示例,创建空间索引:

  1. 使用“CREATE TABLE”:
    CREATE TABLE geom (g GEOMETRY NOT NULL, SPATIAL INDEX(g));
    
  2. 使用“ALTER TABLE”:
    CREATE TABLE geom (g GEOMETRY NOT NULL);
    ALTER TABLE geom ADD SPATIAL INDEX(g);
    
  3. 使用“CREATE INDEX”:
    CREATE TABLE geom (g GEOMETRY NOT NULL);
    CREATE SPATIAL INDEX g ON geom (g);
    
  • SPATIAL INDEX 创建 R 树索引。对于支持空间列的非空间索引的存储引擎,该引擎将创建 B 树索引。空间值的 B 树索引可用于精确值查找,但不适用于范围扫描。


要删除空间索引,请使用“ALTER TABLE”或“DROP INDEX”:

With ALTER TABLE:
ALTER TABLE geom DROP INDEX g;
With DROP INDEX:
DROP INDEX g ON geom;


示例:假设表 geom 包含 32,000 多个几何,这些几何存储在 GEOMETRY 类型的 g 列中。该表还具有“AUTO_INCREMENT”列“fid”,用于存储对象 ID 值。

mysql> DESCRIBE geom;
+-------+----------+------+-----+---------+----------------+
| Field | Type     | Null | Key | Default | Extra          |
+-------+----------+------+-----+---------+----------------+
| fid   | int(11)  |      | PRI | NULL    | auto_increment |
| g     | geometry |      |     |         |                |
+-------+----------+------+-----+---------+----------------+
2 rows in set (0.00 sec)

mysql> SELECT COUNT(*) FROM geom;
+----------+
| count(*) |
+----------+
|    32376 |
+----------+
1 row in set (0.00 sec)

要在列 g 上添加空间索引,请使用以下语句:

mysql> ALTER TABLE geom ADD SPATIAL INDEX(g);
Query OK, 32376 rows affected (4.05 sec)
Records: 32376  Duplicates: 0  Warnings: 0

使用空间索引

优化程序调查在使用 WHERE 子句中使用诸如“MBRContains()”或“MBRWithin()”之类的功能的查询的搜索中是否涉及可用的空间索引。


以下查询查找给定矩形中的所有对象:

mysql> SET @poly =
    -> 'Polygon((30000 15000,
                 31000 15000,
                 31000 16000,
                 30000 16000,
                 30000 15000))';
mysql> SELECT fid,ST_AsText(g) FROM geom WHERE
    -> MBRContains(ST_GeomFromText(@poly),g);
+-----+---------------------------------------------------------------+
| fid | ST_AsText(g)                                                  |
+-----+---------------------------------------------------------------+
|  21 | LINESTRING(30350.4 15828.8,30350.6 15845,30333.8 15845,30 ... |
|  22 | LINESTRING(30350.6 15871.4,30350.6 15887.8,30334 15887.8, ... |
|  23 | LINESTRING(30350.6 15914.2,30350.6 15930.4,30334 15930.4, ... |
|  24 | LINESTRING(30290.2 15823,30290.2 15839.4,30273.4 15839.4, ... |
|  25 | LINESTRING(30291.4 15866.2,30291.6 15882.4,30274.8 15882. ... |
|  26 | LINESTRING(30291.6 15918.2,30291.6 15934.4,30275 15934.4, ... |
| 249 | LINESTRING(30337.8 15938.6,30337.8 15946.8,30320.4 15946. ... |
|   1 | LINESTRING(30250.4 15129.2,30248.8 15138.4,30238.2 15136. ... |
|   2 | LINESTRING(30220.2 15122.8,30217.2 15137.8,30207.6 15136, ... |
|   3 | LINESTRING(30179 15114.4,30176.6 15129.4,30167 15128,3016 ... |
|   4 | LINESTRING(30155.2 15121.4,30140.4 15118.6,30142 15109,30 ... |
|   5 | LINESTRING(30192.4 15085,30177.6 15082.2,30179.2 15072.4, ... |
|   6 | LINESTRING(30244 15087,30229 15086.2,30229.4 15076.4,3024 ... |
|   7 | LINESTRING(30200.6 15059.4,30185.6 15058.6,30186 15048.8, ... |
|  10 | LINESTRING(30179.6 15017.8,30181 15002.8,30190.8 15003.6, ... |
|  11 | LINESTRING(30154.2 15000.4,30168.6 15004.8,30166 15014.2, ... |
|  13 | LINESTRING(30105 15065.8,30108.4 15050.8,30118 15053,3011 ... |
| 154 | LINESTRING(30276.2 15143.8,30261.4 15141,30263 15131.4,30 ... |
| 155 | LINESTRING(30269.8 15084,30269.4 15093.4,30258.6 15093,30 ... |
| 157 | LINESTRING(30128.2 15011,30113.2 15010.2,30113.6 15000.4, ... |
+-----+---------------------------------------------------------------+
20 rows in set (0.00 sec)

使用EXPLAIN检查此查询的执行方式:

mysql> SET @poly =
    -> 'Polygon((30000 15000,
                 31000 15000,
                 31000 16000,
                 30000 16000,
                 30000 15000))';
mysql> EXPLAIN SELECT fid,ST_AsText(g) FROM geom WHERE
    -> MBRContains(ST_GeomFromText(@poly),g)\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: geom
         type: range
possible_keys: g
          key: g
      key_len: 32
          ref: NULL
         rows: 50
        Extra: Using where
1 row in set (0.00 sec)

检查没有空间索引会发生什么:

mysql> SET @poly =
    -> 'Polygon((30000 15000,
                 31000 15000,
                 31000 16000,
                 30000 16000,
                 30000 15000))';
mysql> EXPLAIN SELECT fid,ST_AsText(g) FROM g IGNORE INDEX (g) WHERE
    -> MBRContains(ST_GeomFromText(@poly),g)\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: geom
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 32376
        Extra: Using where
1 row in set (0.00 sec)


在不使用空间索引的情况下执行“SELECT”语句会产生相同的结果,但是会使执行时间从 0.00 秒增加到 0.46 秒:

mysql> SET @poly =
    -> 'Polygon((30000 15000,
                 31000 15000,
                 31000 16000,
                 30000 16000,
                 30000 15000))';
mysql> SELECT fid,ST_AsText(g) FROM geom IGNORE INDEX (g) WHERE
    -> MBRContains(ST_GeomFromText(@poly),g);
+-----+---------------------------------------------------------------+
| fid | ST_AsText(g)                                                  |
+-----+---------------------------------------------------------------+
|   1 | LINESTRING(30250.4 15129.2,30248.8 15138.4,30238.2 15136. ... |
|   2 | LINESTRING(30220.2 15122.8,30217.2 15137.8,30207.6 15136, ... |
|   3 | LINESTRING(30179 15114.4,30176.6 15129.4,30167 15128,3016 ... |
|   4 | LINESTRING(30155.2 15121.4,30140.4 15118.6,30142 15109,30 ... |
|   5 | LINESTRING(30192.4 15085,30177.6 15082.2,30179.2 15072.4, ... |
|   6 | LINESTRING(30244 15087,30229 15086.2,30229.4 15076.4,3024 ... |
|   7 | LINESTRING(30200.6 15059.4,30185.6 15058.6,30186 15048.8, ... |
|  10 | LINESTRING(30179.6 15017.8,30181 15002.8,30190.8 15003.6, ... |
|  11 | LINESTRING(30154.2 15000.4,30168.6 15004.8,30166 15014.2, ... |
|  13 | LINESTRING(30105 15065.8,30108.4 15050.8,30118 15053,3011 ... |
|  21 | LINESTRING(30350.4 15828.8,30350.6 15845,30333.8 15845,30 ... |
|  22 | LINESTRING(30350.6 15871.4,30350.6 15887.8,30334 15887.8, ... |
|  23 | LINESTRING(30350.6 15914.2,30350.6 15930.4,30334 15930.4, ... |
|  24 | LINESTRING(30290.2 15823,30290.2 15839.4,30273.4 15839.4, ... |
|  25 | LINESTRING(30291.4 15866.2,30291.6 15882.4,30274.8 15882. ... |
|  26 | LINESTRING(30291.6 15918.2,30291.6 15934.4,30275 15934.4, ... |
| 154 | LINESTRING(30276.2 15143.8,30261.4 15141,30263 15131.4,30 ... |
| 155 | LINESTRING(30269.8 15084,30269.4 15093.4,30258.6 15093,30 ... |
| 157 | LINESTRING(30128.2 15011,30113.2 15010.2,30113.6 15000.4, ... |
| 249 | LINESTRING(30337.8 15938.6,30337.8 15946.8,30320.4 15946. ... |
+-----+---------------------------------------------------------------+
20 rows in set (0.46 sec)