尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

StarRocks 空间函数 ST_Contains 详解:几何包含关系判定与源码级实现剖析

StarRocks 空间函数 ST_Contains 详解:几何包含关系判定与源码级实现剖析 StarRocks 空间函数 ST_Contains 详解几何包含关系判定与源码级实现剖析【免费下载链接】starrocksThe worlds fastest open query engine for sub-second analytics both on and off the data lakehouse. With the flexibility to support nearly any scenario, StarRocks provides best-in-class performance for multi-dimensional analytics, real-time analytics, and ad-hoc queries. A Linux Foundation project.项目地址: https://gitcode.com/GitHub_Trending/st/starrocksStarRocks 内置了完整的空间Geo函数家族ST_Contains用于判断一个几何图形shape1是否完全包含另一个几何图形shape2是构建地理围栏、区域圈选、轨迹落区等空间分析场景的核心算子。本文以 st_contains.md 为骨架完整讲解其语法、用法与返回值语义并结合 StarRocks 后端BE中 geo_functions.cpp 与 geo_types.cpp 的源码实现剖析其基于 S2 几何库的判定原理与性能优化细节。函数概述ST_Contains(shape1, shape2)是一个布尔类型BOOLEAN的空间关系判定函数用于回答几何图形 shape1 是否完整地包含几何图形 shape2这一问题。当 shape2 的每一个点都位于 shape1 的内部含边界语义由底层 S2 几何库决定时返回1true否则返回0false。典型应用场景包括地理围栏判断设备上报的经纬度点是否落在某个商圈/行政区域内区域圈选从海量带坐标的数据中过滤出落在指定多边形区域内的记录空间关系过滤在 JOIN 或 WHERE 条件中直接使用空间包含关系作为筛选谓词。ST_Contains与空间函数家族中的ST_Point、ST_Polygon、ST_Circle、ST_GeometryFromText等配合使用——前者负责构造几何对象后者负责完成关系判定。语法说明BOOL ST_Contains(GEOMETRY shape1, GEOMETRY shape2)参数说明shape1外层几何图形作为容器参与判定。shape2内层几何图形作为被包含对象参与判定。返回值类型为BOOLEAN返回1shape2 被 shape1 完全包含返回0shape2 存在位于 shape1 之外的部分或 shape1 无法完成包含判定返回NULL任一入参为NULL或传入的几何数据无法被解析为合法几何对象。需要说明的是虽然语法签名写为GEOMETRY但从 BE 实现看两个形参在存储层面均为VARCHAR类型——由ST_Point、ST_Polygon、ST_Circle等构造函数产出的序列化几何编码串见 geo_functions.cpp 中st_contains对两个参数列以ColumnViewerTYPE_VARCHAR进行读取的实现。因此在使用时请确保传入的是几何构造函数的输出而不是裸的 WKT 文本字符串若需从 WKT 文本直接构造几何可先使用ST_GeometryFromText进行转换。使用示例点落在多边形内以下示例构造一个正方形多边形(0 0, 10 0, 10 10, 0 10, 0 0)分别判断点(5, 5)与点(50, 50)是否位于其内部MySQL SELECT ST_Contains(ST_Polygon(POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))), ST_Point(5, 5)); ---------------------------------------------------------------------------------------- | st_contains(st_polygon(POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))), st_point(5.0, 5.0)) | ---------------------------------------------------------------------------------------- | 1 | ---------------------------------------------------------------------------------------- MySQL SELECT ST_Contains(ST_Polygon(POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))), ST_Point(50, 50)); ------------------------------------------------------------------------------------------ | st_contains(st_polygon(POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))), st_point(50.0, 50.0)) | ------------------------------------------------------------------------------------------ | 0 | ------------------------------------------------------------------------------------------第一个查询中(5, 5)位于[0,10] × [0,10]多边形内部返回1第二个查询中(50, 50)明显越界返回0。在表查询中做空间过滤空间函数同样适用于面向表数据的批量计算可将坐标列与区域几何组合直接产出逐行判定结果-- 假设表 locations 保存了设备 id 与其经纬度坐标 SELECT device_id, ST_Contains(ST_Polygon(POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))), ST_Point(lng, lat)) AS inside_region FROM locations;也可以将其作为 WHERE 谓词直接圈选目标区域内的记录SELECT device_id, lng, lat FROM locations WHERE ST_Contains(ST_Polygon(POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))), ST_Point(lng, lat));这种写法在地理围栏告警配送区域匹配等实时分析场景中非常实用避免了把坐标数据导出到外部 GIS 系统再回算的额外链路。与其他空间构造函数的组合shape1不限于多边形也可以是ST_Circle构造的圆形shape2亦可以是线或另一个多边形。例如-- 圆形区域包含点 SELECT ST_Contains(ST_Circle(5, 5, 1000), ST_Point(5.001, 5.001)); -- 多边形包含多边形区域嵌套判断 SELECT ST_Contains(ST_Polygon(POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))), ST_Polygon(POLYGON ((1 1, 2 1, 2 2, 1 2, 1 1))));NULL 与非法输入处理从 geo_functions.cpp 的实现可以确认当任一输入为NULL时结果直接追加NULL当几何数据无法通过GeoShape::from_encoded反序列化返回空指针时同样产出NULL而非报错SELECT ST_Contains(NULL, ST_Point(5, 5)); -- NULL SELECT ST_Contains(not-a-geometry, ST_Point(5, 5)); -- NULL因此在实际使用中建议先通过ST_GeometryFromText等函数保证几何数据的合法性或对可能出现的NULL结果使用COALESCE兜底。包含判定的能力边界从 geo_types.h 的类结构可以推断GeoShape基类的contains()默认返回false只有GeoPolygon多边形与GeoCircle圆形两个子类重写了该虚函数并实现了真实的包含判定逻辑。因此shape1 为多边形或圆形时ST_Contains具备完整的包含判定能力shape1 为点或线等其余几何类型时从源码结构看会落入基类默认实现返回false。若业务需要点在线上线在多边形内等更细粒度关系请关注ST_Contains的扩展方向或借助其他空间谓词组合实现。此外多类型组合的#if 0分支代码见 geo_types.cpp显示StarRocks 在早期迭代中曾规划过多点、多线、多多边形的递归包含判定最终在正式实现中收敛为基于 S2 库的S2Polygon::Contains/S2Cap判定路径边界处理语义以 Google S2 几何库为准。源码级实现剖析ST_Contains的完整链路涉及 FE前端的函数注册与 BE后端的实际计算下面分层展开。1. FE 侧函数注册在 FE 的函数目录中st_contains作为内置空间函数被注册常量定义见 FunctionSet.java// Geo functions: public static final String ST_ASTEXT st_astext; public static final String ST_ASWKT st_aswkt; public static final String ST_CIRCLE st_circle; public static final String ST_CONTAINS st_contains;FE 在解析与优化阶段识别该函数名并下推给 BE 执行SQL 层面对用户完全透明。2. BE 侧求值实现BE 侧的核心实现位于 geo_functions.cpp 的GeoFunctions::st_containsStatusOrColumnPtr GeoFunctions::st_contains(FunctionContext* context, const Columns columns) { ColumnViewerTYPE_VARCHAR lhs_viewer(columns[0]); ColumnViewerTYPE_VARCHAR rhs_viewer(columns[1]); ... for (int row 0; row size; row) { if (lhs_viewer.is_null(row) || rhs_viewer.is_null(row)) { result.append_null(); continue; } ... if (i 2) { result.append(shapes[0]-contains(shapes[1])); } } return result.build(ColumnHelper::is_all_const(columns)); }关键点两个入参均按VARCHAR列读取内部通过GeoShape::from_encoded将序列化字节反序列化为几何对象逐行调用多态方法shapes[0]-contains(shapes[1])完成判定结果通过ColumnBuilderTYPE_BOOLEAN批量产出全程采用列式vectorized处理对整列数据循环求值符合 StarRocks 向量化执行引擎的通用模式。3. S2 几何库的判定内核包含判定的真正内核在几何类型层完成。GeoPolygon::contains位于 geo_types.cpp根据右侧几何类型分发bool GeoPolygon::contains(const GeoShape* rhs) const { switch (rhs-type()) { case GEO_SHAPE_POINT: { const auto* point (const GeoPoint*)rhs; return _polygon-Contains(*point-point()); } case GEO_SHAPE_LINE_STRING: { const auto* line (const GeoLine*)rhs; return _polygon-Contains(*line-polyline()); } case GEO_SHAPE_POLYGON: { const auto* other (const GeoPolygon*)rhs; return _polygon-Contains(other-polygon()); } default: return false; } }多边形内部以 Google S2 库的S2Polygon表示直接调用其Contains方法完成点、线、多边形三类几何的包含判定圆形则以S2Cap球面帽表示GeoCircle::contains见 geo_types.cpp基于帽覆盖关系判断。这意味着ST_Contains的几何模型建立在球面S2坐标体系之上而非简单的平面笛卡尔坐标系长距离、跨经纬度的区域判定在数学上是自洽的。4. 常量折叠优化当shape1或shape2中存在常量列时BE 会启用常量预解码优化。st_contains_prepare位于 geo_functions.cpp在FRAGMENT_LOCAL作用域内若某个入参是常量列ctx-is_constant_column(i)则提前调用一次GeoShape::from_encoded把常量几何解码并缓存到StContainsState中后续逐行求值时命中的行直接复用缓存对象见st_contains中对state-shapes[i]的复用逻辑避免每行重复反序列化若常量列为NULLonly_null()直接标记整体结果为全NULL快速短路返回。这一优化对固定的多边形区域 海量动态坐标点这类典型围栏查询收益显著多边形只需解析一次剩余工作是纯粹的 S2 点包含判定。相关空间函数ST_Contains通常与以下空间函数配合使用全部位于 spatial-functions 目录函数作用文档ST_Point(x, y)由经纬度坐标构造点几何st_point.mdST_Polygon(wkt)由 WKT 文本构造多边形几何st_polygon.mdST_Circle(lng, lat, radius_meter)由圆心与半径米构造圆形几何st_circle.mdST_GeometryFromText(wkt)由通用 WKT 文本构造任意几何st_geometryfromtext.mdST_LineFromText(wkt)由 WKT 文本构造线几何st_linefromtext.mdST_AsText(geom)/ST_AsWKT(geom)将几何序列化为 WKT 文本便于结果可视化与回显st_astext.mdST_X(geom)/ST_Y(geom)提取点几何的横纵坐标st_x.mdST_Distance_Sphere计算两点间球面距离st_distance_sphere.md小结ST_Contains是 StarRocks 空间函数体系中最常用的空间关系算子通过ST_Point、ST_Polygon、ST_Circle等构造几何后即可直接完成包含/不包含判定。其底层基于 Google S2 球面几何库实现支持点、线、多边形、圆形等组合判定BE 侧通过常量折叠与向量化列式计算保证海量坐标场景下的执行效率。结合空间函数家族的其他成员ST_Contains可以无缝嵌入 SQL 查询为地理围栏、区域圈选、空间数据治理等业务提供开箱即用的分析能力。搜索关键词ST_CONTAINS、ST、CONTAINS、空间函数、几何包含、地理围栏。【免费下载链接】starrocksThe worlds fastest open query engine for sub-second analytics both on and off the data lakehouse. With the flexibility to support nearly any scenario, StarRocks provides best-in-class performance for multi-dimensional analytics, real-time analytics, and ad-hoc queries. A Linux Foundation project.项目地址: https://gitcode.com/GitHub_Trending/st/starrocks创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表