十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Apache Spark SQL 地理空间数据类型详解:GEOMETRY 与 GEOGRAPHY 的选型、语法与实践

Apache Spark SQL 地理空间数据类型详解:GEOMETRY 与 GEOGRAPHY 的选型、语法与实践 Apache Spark SQL 地理空间数据类型详解GEOMETRY 与 GEOGRAPHY 的选型、语法与实践【免费下载链接】sparkApache Spark - A unified analytics engine for large-scale data processing项目地址: https://gitcode.com/gh_mirrors/sp/spark本文全面解析 Apache Spark SQL 中基于 OGC Simple Feature Access 规范的GEOMETRY平面笛卡尔坐标系与GEOGRAPHY经纬度地理坐标系两大地理空间数据类型。你将从本文掌握两类类型的适用场景与选型原则、带 SRID 的类型声明语法、基于 WKB 的值构造与校验规则、内置 ST 函数的用法、SRID 注册表与存储兼容性Parquet/Delta/Iceberg并结合当前仓库源码理解其底层实现与错误处理机制。一、GEOMETRY 与 GEOGRAPHY两套坐标体系两种计算模型Spark SQL 支持GEOMETRY与GEOGRAPHY两种地理空间类型其定义遵循 Open Geospatial Consortium (OGC) Simple Feature Access 规范。运行时值以Well-Known Binary (WKB)二进制形式表示并关联一个Spatial Reference Identifier (SRID)以确定其坐标系统值最终如何持久化则由具体数据源决定。类型坐标系典型用途与说明GEOMETRYCartesian平面投影坐标或局部坐标下的平面计算。以平面坐标系表示点、线、多边形适合 Web MercatorSRID 3857、UTM 或局部网格如工程/CAD。可接受注册表中任意 SRID包括 SRID 0未指定 CRS。GEOGRAPHYGeographic经纬度基于地球的数据在球面/椭球面上计算距离与面积。坐标以经度、纬度度表示。边插值始终为SPHERICAL球形。仅接受地理类 SRID最常见为 4326WGS 84。在 SQL 中GEOMETRY和GEOGRAPHY列必须显式声明 SRID或ANY。当通过ST_GeomFromWKB(wkb)不带显式 SRID构造值时该值 SRID 为0未指定而ST_GeogFromWKB(wkb)始终返回 SRID 为 4326 的值。何时选 GEOMETRY数据为局部或投影坐标例如以米为单位的工程/CAD 数据或 Web Mercator 地图瓦片需要在小范围/区域级进行平面运算求交、并集、裁剪、包含关系、叠加分析且把地表当作平面处理误差可接受顶点间距近或范围足够小地球曲率可忽略不计。何时选 GEOGRAPHY数据为全球范围或跨越较大范围例如国界、全球兴趣点距离或面积的计算必须尊重地球曲率例如两城市间最短路径、球面上多边形面积典型场景包括航空、航海、全球移动出行等依赖大圆great-circle或测地线geodesic行为的使用场景。选错类型可能得到误导性结果例如球面上伦敦到纽约的最短路径会穿越加拿大而平面 GEOMETRY 计算可能给出不经过加拿大的路径。二、SQL 类型语法SRID 与 ANY在 SQL 中类型必须携带 SRID 或ANY固定 SRID列内所有值共享同一个 SRIDGEOMETRY(srid)—— 例如GEOMETRY(4326)、GEOMETRY(3857)GEOGRAPHY(srid)—— 例如GEOGRAPHY(4326)混合 SRID列内各值可以有不同的 SRIDGEOMETRY(ANY)GEOGRAPHY(ANY)不带参数、未声明(srid)或(ANY)的裸GEOMETRY/GEOGRAPHY在 SQL 中不受支持。从当前仓库源码看类型层面对「固定/混合」的区分做了显式建模GeometryType.scala 中isMixedSrid通过判断 SRID 是否为MIXED_SRID实现typeName在混合 SRID 时显示为geometry(any)固定 SRID 时显示为geometry($srid)。此外acceptsGeometryType规定了类型兼容规则混合 SRID 类型可接受任意其他 GeometryType固定或混合固定 SRID 类型只接受同 SRID 的 GeometryType且不接受混合 SRID。三、创建带地理空间列的表格-- 固定 SRID所有值必须使用给定 SRID例如 WGS 84 CREATE TABLE points ( id BIGINT, pt GEOMETRY(4326) ); CREATE TABLE locations ( id BIGINT, loc GEOGRAPHY(4326) ); -- 混合 SRID每一行可以有不同 SRID CREATE TABLE mixed_geoms ( id BIGINT, geom GEOMETRY(ANY) );四、构造 GEOMETRY 与 GEOGRAPHY 值值通过内置函数从Well-Known Binary (WKB)构造。WKB 是点、线、多边形等空间形状的标准二进制编码格式。从 WKB二进制构造ST_GeomFromWKB(wkb)—— 返回 SRID 默认值为 0 的 GEOMETRYST_GeomFromWKB(wkb, srid)—— 返回给定 SRID 的 GEOMETRYST_GeogFromWKB(wkb)—— 返回 SRID 为 4326 的 GEOGRAPHY示例WKB 格式的点随后写入表-- Point (1, 2) 的 WKB小端序、2D 点 SELECT ST_GeomFromWKB(X0101000000000000000000F03F0000000000000040); SELECT ST_GeomFromWKB(X0101000000000000000000F03F0000000000000040, 4326); SELECT ST_GeogFromWKB(X0101000000000000000000F03F0000000000000040); INSERT INTO points (id, pt) VALUES (1, ST_GeomFromWKB(X0101000000000000000000F03F0000000000000040, 4326));在源码层面stExpressions.scala 中ST_GeomFromWKB、ST_GeogFromWKB、ST_AsBinary、ST_Srid、ST_SetSrid均实现为RuntimeReplaceable表达式ST_GeomFromWKB(wkb)与ST_GeogFromWKB(wkb)是一元表达式、输入类型为BinaryTypeST_GeomFromWKB(wkb, srid)与ST_SetSrid(geo, srid)为二元表达式ST_Srid、ST_AsBinary的输入限定为GeographyType/GeometryType集合。这意味着这些 ST 函数在 SQL 中可直接与二进制字面量X...组合使用并被规约到统一的内部实现。五、WKB 坐标处理规则解析 WKB 时 Spark 应用以下规则违反任一规则都会产生解析错误空点对于Point几何包括 MultiPoint 内部的点允许NaNNot a Number坐标值表示一个空点如 Well-Known Text 中的POINT EMPTY。LineString与Polygon及其内部的点不允许坐标值为 NaN。非点坐标LineString、Polygon环以及属于这些结构的点坐标值必须为有限值不允许 NaN、正负无穷。无穷大任何坐标值都不接受正无穷或负无穷。多边形环每个环必须闭合首尾点相等且至少 4 个点LineString至少 2 个点。GEOGRAPHY 边界当 WKB 以GEOGRAPHY解析例如通过ST_GeogFromWKB时经度必须在[-180, 180]含端点、纬度必须在[-90, 90]含端点。GEOMETRY 不强制这些边界。无效 WKBNull 或空输入、字节被截断、无效的几何类型或字节序以及其他格式错误的 WKB。六、内置地理空间ST函数Spark SQL 提供一组标量函数处理 GEOMETRY 与 GEOGRAPHY 值。完整函数列表及详细参数说明和示例见 Built-in Functions 页面的Geospatial ST Functions一节。当前版本提供的函数汇总如下函数说明ST_AsBinary(geo[, endianness])将 GEOMETRY 或 GEOGRAPHY 值以 WKBBINARY形式返回。可选endianness参数为NDR小端默认或XDR大端。ST_GeomFromWKB(wkb[, srid])解析 WKB 并返回 GEOMETRY。可选srid参数设置 SRID省略时 SRID 为0。ST_GeogFromWKB(wkb)解析 WKB 并返回 SRID 为 4326 的 GEOGRAPHY。ST_Srid(geo)返回 GEOMETRY 或 GEOGRAPHY 值的 SRID输入为 NULL 时返回 NULL。ST_SetSrid(geo, srid)返回带给定 SRID 的新 GEOMETRY 或 GEOGRAPHY。新 SRID 必须对该值类型有效。关于字节序源码注释明确ST_AsBinary未指定字节序时默认使用小端编码NDR——这正是上面 WKB 示例X01010000...小端点能直接读写回环的原因。示例SELECT hex(ST_AsBinary(ST_GeogFromWKB(X0101000000000000000000F03F0000000000000040))); -- 0101000000000000000000F03F0000000000000040 SELECT hex(ST_AsBinary(ST_GeomFromWKB(X0101000000000000000000F03F0000000000000040), XDR)); -- 00000000013FF00000000000004000000000000000 SELECT ST_Srid(ST_GeogFromWKB(X0101000000000000000000F03F0000000000000040)); -- 4326 SELECT ST_Srid(ST_SetSrid(ST_GeomFromWKB(X0101000000000000000000F03F0000000000000040), 3857)); -- 3857这些函数均在仓库测试中得到了验证例如 st-functions.sql.out 中记录了ST_GeomFromWKB、ST_SetSrid、ST_GeogFromWKB以及CAST(... AS GEOMETRY(4326))等查询的分析结果可直接作为复现参考。七、SRID 与存储值固定 SRID 列列内每个值的 SRID 必须与列类型一致。插入不同 SRID 的值会抛出GEO_ENCODER_SRID_MISMATCH_ERROR。可用ST_SetSrid将值的 SRID 改为与列匹配。混合 SRID 列GEOMETRY(ANY)或GEOGRAPHY(ANY)每行值可以有不同的 SRID。每个值仍须对该类型有效无效 SRID 会抛出ST_INVALID_SRID_VALUE。存储Parquet、Delta、Iceberg 以「每列固定 SRID」方式存储 geometry/geography。它们不支持持久化GEOMETRY(ANY)或GEOGRAPHY(ANY)混合 SRID 类型仅用于内存/查询场景。源码对上述错误与兼容性做了精确实现GeometryType.scala 的assertSridAllowedForType方法固定 SRID 类型下值 SRID 与列 SRID 不一致时抛出GEO_ENCODER_SRID_MISMATCH_ERROR错误参数包含 type、valueSrid、typeSrid混合 SRID 类型下值 SRID 不在支持范围内时抛出ST_INVALID_SRID_VALUE。同一文件中的GeometryType.apply(srid)在构造类型时即通过CartesianSpatialReferenceSystemMapper查注册表查不到即抛ST_INVALID_SRID_VALUEtoSrid对无法识别的 CRS 字符串抛ST_INVALID_CRS_VALUE。ST_INVALID_SRID_VALUE错误类在 QueryExecutionErrors.scala 中统一定义并附带发生错误的 srid 参数。测试层面GeometryDataFrameSuite.scala 与 GeographyDataFrameSuite.scala 分别对GEO_ENCODER_SRID_MISMATCH_ERROR和ST_INVALID_SRID_VALUE做了断言是理解「列 SRID 与值 SRID 校验」行为的最直接参考。另外从源码可以确认类型的一些实现细节GeometryType的defaultSize为 2048 字节约可存储 120 个 2D 点其 JSON 表示使用 CRS 字符串如geometry(OGC:CRS84)这与 Parquet、Delta、Iceberg 的存储规范保持一致类型相等性由 SRID 唯一决定equals/hashCode基于 SRID。八、支持的 SRIDSpark 内置一份预构建的 SRID 注册表由 PROJ 数据库中的坐标系与 OGC 标准覆盖项组合而成用于坐标系的校验与正确处理。SRID 兼容规则GEOMETRY接受注册表中的所有 SRID地理 投影 SRID 0GEOGRAPHY仅接受地理类 SRID经纬度坐标系PROJ 版本与 Spark 版本对照Spark 版本PROJ 版本4.2.09.8.1SRID 注册表固定绑定上表中的 PROJ 版本不会与外部数据库实时同步。OGC 标准覆盖项Spark 对 PROJ 数据库中的部分 SRID 应用了 OGC 标准覆盖SRIDPROJ CRS 标识OGC CRS 标识说明4326EPSG:4326OGC:CRS84WGS 84按 OGC 标准为经度/纬度顺序4267EPSG:4267OGC:CRS27NAD274269EPSG:4269OGC:CRS83NAD83常用 SRIDSRIDCRS 标识名称CRS 类型说明0SRID:0UnspecifiedCartesian未定义 CRS 的坐标ST_GeomFromWKB(wkb)的默认值4326OGC:CRS84WGS 84Geographic1984 世界大地坐标系经度/纬度GPS 坐标、全球数据GEOGRAPHY 默认4267OGC:CRS27NAD27Geographic北美 1927 大地基准4269OGC:CRS83NAD83Geographic北美 1983 大地基准3857EPSG:3857Web MercatorProjectedWeb 地图服务使用的伪墨卡托投影注意事项GEOMETRY(0)表示固定 SRID 为 0。若需要每行不同 SRID请使用GEOMETRY(ANY)。Parquet 与 Iceberg 的地理空间规范要求每列固定 SRID因此不支持持久化GEOMETRY(ANY)或GEOGRAPHY(ANY)。SRID 校验示例无效 SRID不在注册表中SELECT ST_GeomFromWKB(X0101000000000000000000F03F0000000000000040, 99999); -- Throws [ST_INVALID_SRID_VALUE]投影 SRID 用于 GEOGRAPHY 类型CREATE TABLE invalid_geo (id BIGINT, loc GEOGRAPHY(3857)); -- Throws [ST_INVALID_SRID_VALUE] (3857 is projected, not geographic)九、数据类型的 API 参考关于 Scala、Java、Python、SQL 中完整的数据类型列表与 API 用法参见 Data Types 文档全部 ST 函数的签名、参数与示例参见 Built-in Functions 中 Geospatial ST Functions 章节。本文所涉及的 Geo 类型与函数实现集中位于 sql/api 的 types 包 与 catalyst 的 expressions/st 包测试与示例可进一步参阅 GeometryDataFrameSuite.scala、GeographyDataFrameSuite.scala 及 st-functions.sql.out。【免费下载链接】sparkApache Spark - A unified analytics engine for large-scale data processing项目地址: https://gitcode.com/gh_mirrors/sp/spark创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表