引用博客/论文
空间连接
声明:以下内容直接来源于[引用1]
空间连接(Spatial Join)运算是一类最常用的空间数据分析算子,具有广泛的应用场景。例如统计地铁站周围500米的POI,帮助店主合理选择商铺选址;从同一个数据集中分析空间相邻的同伴关系,辅助警方侦察;查询河流周围的居民区和农田,在汛期排除洪水隐患;查找去过疫区的人群,方便疫情防控等。
下面给出空间连接的定义:给定空间对相集合R和S以及空间谓词θ,计算并输出所有空间对象二元组(r, s),满足r∈R,s∈S,且r和s满足空间谓词θ,形式化定义如下。
空间谓词θ可以分为三类。
1)空间拓扑:如intersects(相交)、contains(包含)等;
2)空间距离:即distance,表示空间对象s与r的空间距离小于等于设定阈值δ,由定义(1)派生出distance连接的定义如下。
另外,空间对象可分为三种类型:点(Point)、线(LineString)、面(Polygon)。点是最简单的空间对象,线和面是复杂空间对象,其空间运算相对耗时。为了简化计算,一般用空间对象的最小边界矩形MBR(Minimum Bounding Rectangle)进行空间运算,得到近似结果,然后对近似结果进一步提纯过滤,得到最终的精确解。
空间连接运算是基于空间索引实现的,空间索引能够通过快速过滤来提高查询效率,基于空间索引的空间连接的运算过程如下:
1)构建空间索引。对集合S中所有空间对象s,利用s.mbr构建空间索引I。
2)循环查询。对集合R中的每个空间对象r, 用r查询索引I中与其满足空间谓词θ的所有空间对象s,并将二元组(r, s)加入结果集。
空间索引不止一种,选取合理的空间索引对提高空间连接运算的性能至关重要。为了验证空间索引对空间连接运算性能的影响,本文首先在第2节中介绍几种最常用的空间索引。然后在第3节进行实验对比,分别以空间索引、空间对象类型、空间连接谓词为变量,分析影响空间连接运算性能的因素。
空间索引
空间索引一般是基于数据结构中的树来实现的。在索引树上,一个节点对应一个矩形的空间范围,父节点的空间范围包含所有子节点的空间范围。空间对象依据其MBR,存储在树的对应节点上。在查询时,首先依据查询对象的MBR遍历树上与该MBR相交的所有节点,并收集节点上存储的空间对象作为一个候选结果集,最后再根据空间谓词θ做进一步过滤,保留满足空间谓词的候选对象,组成最终的结果集。下面分别介绍三种最常用的空间索引:Quadtree索引、KDtree索引和Rtree索引,且设定用数据集S构建索引,然后用数据集R中的空间对象r查询空间索引。
Quadtree索引
Quadtree[1]索引是一棵四叉树,支持所有空间对象类型。Quadtree将集合S的全局空间范围G递归地划分成4子空间,直到子空间内的空间对象数量小于等于设定的阈值α,并对四个子空间分别编号0、1、2、3,如图1(a)所示(α = 1)。然后用四叉树结构组织所有子空间,如图1(b)所示,树的根节点对应空间范围G,一个节点对应一个子空间。对数据集S中的空间对象s,将其存储在包含s.mbr的最小子空间对应的节点中,当s是空间点时,s与s.mbr空间上等价,所有空间点均存储在叶子节点中,如图1所示。
图1 Quadtree索引
在查询时,使用r.mbr近似表示空间对象r,查找Quadtree中与r.mbr相交的节点,然后判断节点中的所有空间对象s是否与r存在空间相交关系。图1中,红色的矩形表示r.mbr,该矩形在Quadtree上遍历的节点标记为红色,然后找到叶子节点233上与其相交的一个空间点s,最后再判断r和s的相交关系。通过空间索引,可以快速过滤掉与查询框r.mbr不相交的节点,加快遍历查询效率。
KDtree索引
KDtree索引是一棵二叉树,仅支持空间点对象。在构建索引时,首先使用集合S中第一个空间点s1的构建根节点root,根节点包含空间点s1和标签odd,odd是个布尔值,true表示该节点用s1.x进行空间划分,false表示用s1.y,KDtree中父节点和子节点的odd相反,即交替地使用x和y值进行空间划分。对于后续的空间点si(i>1),以root节点为当前节点,递归地执行以下步骤:
1)判断当前节点是否为叶子节点,若是执行步骤2),若不是执行步骤3);
2)设当前节点中存储的空间点是s,odd = true时根据s.x的值将当前节点对应的空间范围一分为二生成两个子节点,反之根据s.y的值进行划分。然后根据si.x(或si.y)与s.x(或s.y)的大小关系,将si保存到对应子节点上,子节点的odd值与当前节点相反;
3)利用步骤2)中描述的判断方法,得到子节点,并将其设为当前节点,然后执行步骤1)。
图2 KDtree索引
在构建好的KDtree索引中,每个空间点对应一个节点(叶子或非叶子节点),如图2所示。
查询时,用r.mbr遍历树上所有与之相交的节点,然后摘取节点上的空间点s并判断r与s是否空间相交。在图2中,红色矩形表示r.mbr,它在KDtree上遍历的节点用红色标记。
2.3 Rtree索引
Rtree索引是一棵多叉树空间聚类,对集合S中的所有空间对象聚类,生成n个聚类,然后自底向上递归地对n份聚类进一步执行聚类,直到n = 1。Rtree中一个节点对应一个聚类,与Quadtree和KDtree不同的是,Rtree同一级别的节点之前可以存在重叠,这保证了一个空间对象仅属于一个Rtree的叶子节点,即Rtree中所有空间对象之存储在叶子节点中,如图3所示。
图3 Rtree索引
下面介绍一种JTS[5](Java Topology Suite)实现的一种Rtree索引——STRtree[4]。该索引的构建步骤如下:
- 初始化集合C = {c1,c2,c3,..,cn}, ci是仅包含一个空间对象si的空间聚类,ci.mbr = si.mbr,n是集合S中的空间对象数量。
-
STRtree有一个阈值m,表示一个非叶子节点所包含的最大子节点数量。γ = ⌈n/m⌉ 表示集合C需要被划分成γ个聚类。如果γ = 1,说明n ≤ m,则将集合C聚类成一个根节点Root,ci是Root的子节点,构建索引完成。如果γ > 1,则执行步骤3)。
-
ε = ⌈sqrt(γ)⌉表示每个聚类在x和y方向上划分的份数。对集合C按照ci.mbr.minx在x方向递增排序,然后将其在x方向上平均地划分为ε份聚类,然后对每份结果在y方向上按照ci.mbr.miny排序并平均地划分成ε份聚类,两次划分生成大于等于γ份的聚类 ,γ ≤ k < n,集合C中的聚类是集合C’中聚类的子节点。用C’替换C,然后执行步骤2)。
在查询时,同样用r.mbr遍历STRtree中与之相交的节点,并收集叶子节点上存储的所有空间对象s,然后判断r和s是否空间相交。遍历过程如图3中红色节点所示。