ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Apache Druid 空间索引与空间过滤器(Spatial Filter)实战指南

Apache Druid 空间索引与空间过滤器(Spatial Filter)实战指南 数据库OLAP大数据后端【免费下载链接】druidApache Druid: a high performance real-time analytics database.项目地址https://gitcode.com/gh_mirrors/druid6/druid点击查看免费下载本文围绕 Apache Druid 原生查询语言中的空间过滤能力展开系统讲解如何在摄入阶段构建空间维度Spatial Dimension、在查询阶段使用矩形rectangular、半径radius与多边形polygon三种空间边界Bound过滤数据并结合仓库源码深入剖析其底层 RTree 索引与点包含判定原理。读完本文你将能够配置带空间索引的数据摄入规格并在 native 查询中编写正确、高效的空间过滤条件。:::info 说明 Apache Druid 支持 Druid SQL 与 native 查询 两种查询语言。本文所述的空间过滤特性仅适用于 native 语言Druid SQL 中尚无对应的空间过滤语法。关于 Druid 支持的其他过滤器参见 Query filters。 :::空间索引Spatial indexing空间索引Spatial indexing是指将空间数据类型如 geometry、geography的数据摄入到 Druid 中使后续查询可以基于原点 边界origin and bound的方式对空间索引列进行过滤。在 Druid 中空间维度spatial dimension本质上是字符串列其取值是用逗号分隔的坐标序列例如30.0,40.0。空间维度可以来自输入数据中已有的坐标数组也可以由多个普通维度拼接构造而来。空间维度在摄入规格ingestion spec的dataSchema组件下的dimensionsSpec对象中进行配置并且可以采用 Druid 支持的任意数据格式提供。下面是一个使用 Hadoop 摄入type 为hadoop的示例它定义了名为coordinates的空间维度由输入字段x与y构造而成{ type: hadoop, dataSchema: { dataSource: DatasourceName, parser: { type: string, parseSpec: { format: json, timestampSpec: { column: timestamp, format: auto }, dimensionsSpec: { dimensions: [ { type: double, name: x }, { type: double, name: y } ], spatialDimensions: [ { dimName: coordinates, dims: [ x, y ] } ] } } } } }spatialDimensions 配置字段spatialDimensions数组中的每个空间维度对象由以下字段定义属性描述必填dimName空间维度的名称。空间维度可以由其他维度构造也可以作为事件的已有字段存在如果空间维度已经存在那么它必须是一个坐标值数组。是dims构成该空间维度的维度名称列表。否一个值得注意的细节是空间维度与普通维度是互斥的。从源码 SpatialDimensionRowTransformer 的实现可以看出在摄入阶段 Druid 会把所有空间维度以及构成空间维度的部分维度从普通维度集合中剔除并将它们拼接为逗号分隔的字符串存储同时该转换器会丢弃所有无效的空间维度源码注释原文We throw away all invalid spatial dimensions。因此同一列不应同时出现在dimensions与spatialDimensions中。关于摄入规格的完整用法参见 Ingestion spec reference关于 Druid 数据加载的一般性介绍参见 Ingestion。空间索引的底层存储从源码结构看空间维度的索引基于RTreeR 树实现段内索引通过 SpatialIndex 接口暴露其核心方法getRTree()返回一棵不可变的 R 树BaseImmutableRTee。查询执行时SpatialFilter 从列的索引供应器ColumnIndexSupplier中取出SpatialIndex调用spatialIndex.getRTree().search(bound)在 R 树上搜索与边界相交的所有叶子节点再通过bitmapResultFactory.unionDimensionValueBitmaps(search)将命中的位图bitmap合并为最终结果。这意味着空间过滤在大多数情况下可以直接走索引而非逐行扫描这也是将空间数据建模为空间维度的价值所在。空间过滤器Spatial filters在 native 查询中filter 是一个 JSON 对象用于指明哪些行应被纳入查询计算。Druid 提供了spatial类型过滤器可以对矩形、半径圆、多边形等空间结构进行过滤。空间过滤器具有如下结构filter: { type: spatial, dimension: name_of_spatial_dimension, bound: bound_type }一个使用矩形边界的完整示例filter : { type: spatial, dimension: spatialDim, bound: { type: rectangular, minCoords: [10.0, 20.0], maxCoords: [30.0, 40.0] } }注意空间过滤器中维度坐标的顺序必须与spatialDimensions数组中维度坐标的顺序一致。例如摄入时spatialDimensions按[x, y]的顺序构造了coordinates那么过滤时minCoords与maxCoords也必须是[x, y]的顺序。在源码层面native 查询中的空间过滤器由 SpatialDimFilter 表示它通过 Jackson 注解接收dimension、bound以及可选的filterTuning三个属性并校验dimension与bound均不可为 nulltoFilter()方法将其转换为段执行层使用的 SpatialFilter。SpatialFilter同时实现了位图索引路径与值匹配ValueMatcher路径索引路径优先尝试SpatialIndex.getRTree().search(bound)走 RTree 索引前提是列上存在SpatialIndex否则退化为全未知位图或逐值匹配。匹配路径内部类BoundDruidPredicateFactory仅支持字符串与对象谓词makeStringPredicate/makeObjectPredicate对于 long、float、double 类型的谓词一律返回ALWAYS_FALSE——从源码注释看SpatialFilter 当前不支持 long/float/double见 SpatialFilter.java因此空间维度应建模为字符串/对象列。该过滤器支持向量化canVectorizeMatcher返回true。边界类型Bound typesbound属性决定对维度值范围的过滤方式共支持三种矩形rectangular、半径radius与多边形polygon。这三种类型在 Bound 接口的 Jackson 子类型声明中注册对应实现类为RectangularBound、RadiusBound与PolygonBound。矩形Rectangularrectangular边界包含以下元素属性描述必填minCoords最小维度坐标列表形式为 [x, y]是maxCoords最大维度坐标列表形式为 [x, y]是其判定逻辑最为直接点在 R 树搜索时凡落在[minCoords, maxCoords]包围盒内的叶子节点即被命中。矩形边界也是其他两类边界的底座——例如半径边界正是先构造一个外接矩形进行粗筛再在矩形内做精确的距离判定。半径Radiusradius边界包含以下元素属性描述必填coords圆心坐标形式为 [x, y]是radius依据指定单位解释的浮点半径值是radiusUnit半径单位的小写字符串默认值为euclidean。允许的单位euclidean、meters、miles、kilometers。否从 RadiusBound 的实现可以看到半径过滤的完整流程构造外接矩形粗筛构造时通过getMinCoords/getMaxCoords将圆心坐标各维分别减去/加上radius得到一个内接于圆的矩形作为 R 树搜索的包围盒super(getMinCoords(coords, radius), getMaxCoords(coords, radius), limit)用于在 R 树上快速定位候选点集。精确距离判定contains()方法按单位区分两种算法单位euclidean欧氏距离直接比较各维坐标差平方和与radius²的大小total Math.pow(radius, 2)单位meters/miles/kilometers地理距离使用 RTreeUtils.calculateHaversineDistance 计算两点间的大圆距离Haversine 公式并与按单位换算后的米制半径radius * radiusUnit.getMetersMultiFactor()比较。RadiusUnit枚举见 RadiusBound.java中euclidean与meters的换算系数为 1miles为 1609.344 米kilometers为 1000 米当radiusUnit未指定时默认取euclidean。这意味着如果你的坐标是经纬度如[lon, lat]应使用meters/miles/kilometers单位以获得符合地理语义的距离如果你的坐标是平面直角坐标则使用默认的euclidean即可。多边形Polygonpolygon边界包含以下元素属性描述必填abscissa多边形各角点的水平坐标横坐标是ordinate多边形各角点的垂直坐标纵坐标是abscissa与ordinate按角点一一对应共同描述多边形顶点序列。多边形至少需要 3 个角点源码 PolygonBound.from 中通过Preconditions.checkArgument(abscissa.length 2)强制要求且abscissa与ordinate的长度必须相等。从 PolygonBound.contains 的实现可以看出多边形包含判定采用经典的射线法odd-even rule若点恰为某个角点abscissa[i] coords[0] ordinate[i] coords[1]直接返回true若点落在某条水平边上isPointLayingOnHorizontalBound返回true否则从点出发向水平方向引射线统计与多边形边界的交点个数交点个数为奇数则点在多边形内oddNodes变量翻转否则在外当交点恰好经过顶点横坐标时intersectionPointX coords[0]也判定为点在多边形上。因此多边形边界支持任意凸多边形与凹多边形且点在边界上的情况会被判定为命中。实战完整的空间过滤查询示例将上述内容组合起来一个完整的时间序列timeseriesnative 查询可以写成{ queryType: timeseries, dataSource: DatasourceName, intervals: [2013-01-01/2013-01-07], granularity: day, aggregations: [ { type: count, name: rows } ], filter: { type: spatial, dimension: coordinates, bound: { type: radius, coords: [10.0, 20.0], radius: 1000.0, radiusUnit: kilometers } } }该查询会从coordinates空间维度中筛选出以(10.0, 20.0)为圆心、半径 1000 公里按 Haversine 大圆距离计算范围内的所有行。若将bound换成rectangular或polygon即可实现矩形范围或任意多边形范围的空间过滤。验证与测试仓库中提供了丰富的测试用例可用于验证空间过滤的语义与索引行为SpatialFilterTest构造了 5000 个随机点NUM_POINTS 5000在增量索引段IncrementalIndexSegment与磁盘段QueryableIndexSegment两种段形态上对RectangularBound、RadiusBound等进行参数化测试并交叉验证索引位图结果与逐行匹配结果的一致性。SpatialFilterBonusTest对空间过滤的补充性场景测试。IndexMergerV9WithSpatialIndexTest验证 V9 段合并IndexMergerV9过程中空间索引的正确构建与持久化。小结与使用建议空间维度是字符串列值为逗号分隔的坐标序列在dimensionsSpec.spatialDimensions中声明可由其他维度构造也可直接使用事件中已有的坐标数组。空间过滤是 native 查询专属能力Druid SQL 暂不支持过滤器通过dimensionbound描述坐标顺序必须与摄入时的spatialDimensions顺序一致。三种边界各有所长rectangular适合规则矩形范围radius提供欧氏距离与米/英里/千米三种地理距离单位经纬度场景请使用地理单位polygon支持任意凸凹多边形采用射线法判定。性能上优先走 RTree 索引只要列上存在空间索引SpatialFilter就会通过SpatialIndex.getRTree().search(bound)直接产出命中位图无需全量扫描同时它支持向量化匹配路径可被集成到向量化查询执行中。结合查询过滤器与摄入规格文档你可以在自己的 Druid 集群中快速落地基于空间范围的数据筛选能力。赞分享数据库OLAP大数据后端【免费下载链接】druidApache Druid: a high performance real-time analytics database.项目地址https://gitcode.com/gh_mirrors/druid6/druid点击查看免费下载相关推荐Apache Druid 地理查询Geographic Queries完整指南空间索引、Spatial Filter 与 RTree 底层原理Apache Druid 地理查询Geographic Queries完整指南空间索引、Spatial Filter 与 RTree 底层原理 本文基于数据库数据分析OLAP大数据实时分析数据仓库后端G-Helper华硕笔记本终极轻量控制工具告别Armoury Crate臃肿体验G Helper华硕笔记本终极轻量控制工具告别Armoury Crate臃肿体验 你是否厌倦了华硕Armoury Crate的缓慢启动、高内存占用和复杂操作桌面应用系统编程Haskell深度学习实战用Grenade构建生成对抗网络(GAN)的完整指南Haskell深度学习实战用Grenade构建生成对抗网络 GAN 的完整指南 Grenade是一个基于Haskell语言的深度学习框架专为构建和训练神经网创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表