MaxCompute 原生支持 GEOGRAPHY 地理空间数据类型,用于表示地球表面的点、线、多边形等几何对象,支持空间数据的存储、构造和运算,用于高效存储与操作地理空间数据。MaxCompute 的 GEOGRAPHY 类型底层采用 S2 Geometry 库实现。
支持几何类型
MaxCompute 支持构建以下几何类型:
几何类型 | 描述 |
Point(点) | 地球表面的一个位置,由经度和纬度坐标描述,经度在前,纬度在后。示例如下: |
LineString(线) | 一维曲线,由一系列点及其连接的测地线组成。示例如下: |
Polygon(多边形) | 二维面,用一条或者多条闭合的曲线来描述,其中第1条闭合的曲线用来描述它的外边界,其他闭合曲线(如果存在)则描述多边形中的洞,Polygon 中的洞用于描述多边形内部的排除区域。示例如下: |
MultiPoint | 多个点的集合。 |
MultiLineString | 多条线段的集合。 |
MultiPolygon | 多个多边形的集合。 |
GeometryCollection | 多种几何类型对象的集合。 |
坐标以(经度, 纬度)形式给出,单位为度,遵循 WGS84 地理坐标系。经度应在 [-180, 180] 范围内,纬度应在 [-90, 90] 范围内。
MaxCompute 的 GEOGRAPHY 类型底层采用 S2 Geometry库实现。与传统 GIS(地理信息系统)库最大的不同是,S2 不使用任何平面地图投影(如墨卡托投影),而是直接将地球视为一个完美的球体。地球上的经纬度坐标首先会被转换成球体上的三维笛卡尔坐标 (x, y, z),因此在两极也不会产生平面投影导致的计算误差增大问题。
S2 地理库使用 DOUBLE 类型描述地理对象的坐标,将输入的数据转换为 S2 地理库对象时可能会有极微小的精度损失,导致输入和输出之间存在非常微小的差异。
使用限制
客户端版本限制:查询 GEOGRAPHY 类型数据时,若使用本地客户端 odpscmd,需使用 0.56.0 及以上版本,且不支持设置
use_instance_tunnel=true。数据类型限制:1.0 数据类型不支持GEOGRAPHY 类型数据,使用时需要在 project 级别或 session 级别设置
odps.sql.type.system.odps2=true;开启 2.0 数据类型版本。GEOGRAPHY 类型不支持比较操作,因此不能用于 SELECT DISTINCT、GROUP BY、ORDER BY 或作为 JOIN 的等值连接条件。
GEOGRAPHY 类型暂不支持地理类型对象的 Z(高程)或 M(测量值)维度。
GEOGRAPHY 类型不支持构造大于半个地球球体的地理对象。示例如下:若希望通过如下 SQL 语句构造一个从西经 179 度到东经 179 度之间几乎覆盖整个地球的地理对象,而实际上得到的是一个小于半球的地理对象,其经度范围是从东经 179 度向东,越过 180 度经线,然后到达西经 179 度。
SELECT ST_GEOGFROMTEXT( 'POLYGON ((-179 -89, 179 -89, 179 89, -179 89, -179 -89))' ); -- 返回结果: +------+ | _c0 | +------+ | POLYGON ((-179 89, 179 89, 179 -89, -179 -89, -179 89)) | +------+
创建与使用 GEOGRAPHY 数据
建表时可直接使用 GEOGRAPHY 类型作为字段类型:
SET odps.sql.type.system.odps2=true;
CREATE TABLE spatial_points (
id BIGINT,
name STRING,
location GEOGRAPHY,
region GEOGRAPHY
);支持使用内建函数(如 ST_GEOGPOINT、ST_GEOGFROMTEXT、ST_GEOGFROMWKB、ST_MAKELINE 和 ST_MAKEPOLYGON 函数)来构造地理类型对象,详情请参见地理函数概述。
-- 插入数据:使用地理函数构造 GEOGRAPHY 对象
INSERT INTO spatial_points VALUES
(1, '北京中心', ST_GEOGPOINT(116.4074, 39.9042),
ST_GEOGFROMTEXT('POLYGON((116.3 39.8, 116.5 39.8, 116.5 40.0, 116.3 40.0, 116.3 39.8))')),
(2, '上海外滩', ST_GEOGPOINT(121.4894, 31.2403),
ST_MAKEPOLYGON(ST_MAKELINE(ARRAY(
ST_GEOGPOINT(121.4, 31.2),
ST_GEOGPOINT(121.5, 31.2),
ST_GEOGPOINT(121.5, 31.3),
ST_GEOGPOINT(121.4, 31.3),
ST_GEOGPOINT(121.4, 31.2)
))));
-- 查询插入的数据
SELECT * FROM spatial_points;
-- 返回结果:
+------------+---------+--------------------------+--------+
| id | name | location | region |
+------------+---------+--------------------------+--------+
| 1 | 北京中心 | POINT (116.4074 39.9042) | POLYGON ((116.3 39.8, 116.5 39.8, 116.5 40, 116.3 40, 116.3 39.8)) |
| 2 | 上海外滩 | POINT (121.4894 31.2403) | POLYGON ((121.4 31.2, 121.5 31.2, 121.5 31.3, 121.4 31.3, 121.4 31.2)) |
+------------+---------+--------------------------+--------+地理函数
MaxCompute 提供一系列以 ST_ 开头的地理函数,用于构造、转换和分析 GEOGRAPHY 类型的地理数据。通过这些函数,可以从经纬度坐标或 WKT/WKB 文本创建点、线、多边形等地理对象,提取坐标、边界框等属性信息,判断地理对象之间的包含、相交、覆盖等空间关系,以及计算地理对象之间的距离。
更多详情请参见地理函数概述。
目前支持的地理函数如下:
分类 | 函数 | 说明 |
构造与解析 | 通过指定的经度和纬度构造一个 Point 类型的地理对象 | |
通过指定的端点构造 LineString 类型的地理对象 | ||
通过指定外部边界(shell)和 0 个或多个洞(hole)构造 Polygon 类型的地理对象 | ||
将 WKT 格式的字符串转换为 GEOGRAPHY 类型的地理对象 | ||
将 WKB 格式的 BINARY 数据转换为 GEOGRAPHY 类型的地理对象 | ||
格式化 | 将 GEOGRAPHY 值转换为 BINARY 类型的 WKB 格式 | |
将 GEOGRAPHY 值转换为 STRING 类型的 WKT 格式 | ||
属性访问 | 获取 GEOGRAPHY 值的 BoundingBox 信息 | |
从 POINT 类型的地理对象中获取经度值 | ||
从 POINT 类型的地理对象中获取纬度值 | ||
空间运算 | 判断 value1 对应的地理对象是否包含 value2 对应的地理对象 | |
判断 value1 对应的地理对象是否覆盖 value2 对应的地理对象(value2 的所有点均在 value1 的边界或内部) | ||
判断两个地理对象是否相交(存在至少一个公共点) | ||
判断 value1 对应的地理对象是否被包含在 value2 对应的地理对象中 | ||
判断两个地理对象之间的最短距离是否小于或等于指定的距离值 | ||
计算两个地理对象之间的最短距离,单位为米 |
空间连接(Spatial Join)
空间连接(Spatial Join)是在两个包含 GEOGRAPHY 类型数据的表之间,基于空间谓词函数(如 ST_CONTAINS、ST_INTERSECTS 等)判断地理对象之间的空间关系,并以此作为连接条件的非等值连接操作。
通常用法:表中存储 GEOGRAPHY 列,地理函数判断空间关系,JOIN 将两者串联为连接条件。
典型场景包括:判断兴趣点(POI)是否落在指定区域内、分析轨迹与地理围栏的交叉关系等。
MaxCompute 基于广播小表实现空间连接,使用时须通过 MAPJOIN HINT 指定需广播的小表。
更多详情请参见Spatial JOIN(空间连接)。