R-Tree 学习笔记

R-Tree 学习笔记

引言

空间数据对象(spatial data objects)通常是一个在多维空间中区域,不能仅用坐标点位置很好的表示。
例如,在地图应用中,代表一个国家的空间数据对象,就是一个在二维空间中的区域。
对于空间数据的常用操作就是查找一个区域中的所有对象,所以根据空间数据对象所表示的区域范围,高效的获取该区域中的空间数据对象,是很重要的。

传统的一维数据库索引并不适合多维的空间搜索。如基于hash的索引结构适用于精确匹配查找值的搜索,而空间数据搜索通常是范围查找,而B-Tress这样的一维排序键值所以又难以满足对多维数据索引。

R-Tree索引的结构

一个空间数据库由一系列对应空间对象的tuple组成,而每一个tuple具有一个唯一标示(tuple identifier,简称tupleID吧),数据库可以通过这个唯一标示获取到该tuple。
R-Tree所做的就是将这些tupleID索引起来。

叶子节点

每一个叶子节点包含一组索引记录(index record,后文称之为entry)。
每个entry的格式如下:
\[(MBR,tupleID)\]
其中,MBR(Minimum Bounding Region)表示可以框住tupleID所对应的空间数据对象的最小N维矩形。
\[MBR=(MBR_0,MBR_1,...,MBR_{n-1})\]
其中n为\(MBR\)所在空间维度,\(MBR_i\)为该\(MBR\)在第i个维度上的值,通常是一个闭区间范围[a,b]

tupleID为一个指向数据对象的指针。

非叶子结点

非叶子节点的包含的entry格式如下:
\[(MBR,child-pointer)\]
其中,\(child-pointer\)为指向其子节点的指针。而\(MBR\)则是一个可以框住其\(child-pointer\)对应的子节点上所有entry包含的\(MBR\)的最小N维矩形。

节点中包含entry的数量

对于一个基于磁盘存储的R-Tree索引,其每一个节点对应一个磁盘页(page)。为了节省磁盘IO,同时尽可能高效的利用磁盘空间,
M为一个节点所能包含的entry的最大值,m为一个节点包含entry的最小值,有\(m \leq \frac{M}{2}\)

总结

R-Tree具有以下属性:

  1. 每个节点的包含的entry的个数范围[m,M],除非该节点是根节点
  2. 对于叶子节点中每一条entry(MBR,tupleID),其中MBR表示能框住其tupleID所对应的空间对象的最小N维矩形。
  3. 对于非叶子节点中的每一条entry(MBR,child-pointer),其中MBR表示能框住其子节点中所有entry对应的空间对象的MBR的最小N维矩形。
  4. 根节点由至少两个子节点,除非该节点同时也是叶子节点
  5. 所有叶子节点出现在同一层。

包含N条索引记录的R-Tree:

  • 最大高度为\(\lceil \lg_m{M} \rceil -1\),因为每个节点最少由m个子节点。
  • 最大节点数量\(\lceil \frac{N}{m}\rceil+\lceil\frac{N}{m^2} \rceil+\dots+1\)
  • 除根节点外空间利用率最低为\(\frac{m}{M}\)

数据操作

  • EI:一条索引记录(entry)中MBR
  • Ep:一条索引记录(entry)中的tupleID或child-pointer

搜索

Search 在根节点为T的R-Tree中搜索一个MBR为S的空间数据对象

  1. 从节点T开始搜索,如果该节点不是根叶子节点,那么分别查看该节点上每一个entry所对应的EI是否与S重合。对所有有重合部分的entry,继续搜索其Ep指向的子节点。
  2. 如果该节点是叶子节点,查看该节点上是否存在EI与S重合,如果有则说明该EI对应的entry为需要检索的记录。

插入

Insert 为新的空间数据对象(tuple)插入索引记录(index record)

  1. 通过ChooseLeaf过程,查找将要插入entry的叶子节点
  2. 如果叶节点有空间则直接插入,否则调用SplitNode过程进行节点分裂
  3. 调用AjustTree过程,向上层传播节点的变化,包括可能产生的节点分裂与新entry加入引起的EI的变化
  4. 如果节点变化的传播最终导致根节点分裂,则创建一个新的根节点作为原根节点分裂后的父节点,即R-Tree向上生长了一层

ChooseLeaf 选择一个叶子节点放置索引记录F

  1. 从根节点N开始查找
  2. 如果N为叶子节点,则直接返回节点N
  3. 如果N不是叶子节点,则分别查看节点N中所有的entry,选择包含FI后扩展量最小的entry,如果扩展量相同,则选择EI最小的E
  4. 以Ep所指向的子节点为为根,继续步骤2

AdjustTree 从叶子节点L向上传播MBR值的变化,以及可能发生的节点分裂

  1. 令N=L,如果L发生了分裂,则令NN为分裂后的另一个节点
  2. 如果N为根节点,则停止。(如果R-Tree只有一层,根节点也是叶子节点,那么MBR的改变无需向上传播)
  3. 找到节点N的父节点P,并调整N在P中的对应entry的MBR值,使之可以包含节点N中所有的EI
  4. 如果NN存在,则创建一个新的entry(\(E_NN,E_{NN}p\)),如果P中有空间,则将其插入P中,否则调用SplitNode过程,产生节点P与PP
  5. 令N=P,如果P节点发生分裂,则灵NN=PP,重复2(逐层向上传播)

删除

Delete 删除索引记录E

  1. 调用FindLeaf以定位包含索引记录E的叶子节点L,如果没有没有找到则停止
  2. 从L中删除E
  3. 调用CondenseTree从L向上传播节点的变化
  4. 如果根节点只剩一个子节点,则令该子节点成为新的根节点,即R-Tree减少一层

FindLeaf 在R-Tree T中查找包含entry F的叶子节点L

  1. 如果T不是叶子节点,则查看节点中每一个entry,对每一个与F重合的entry,以Ep指向的子节点为根,调用FindLeaf过程,直到F被找到或者所有的entry都检查过但仍为找到F
  2. 如果T是叶子节点,则查看T中是否包含与F相符合的entry,如果有则返回T

CondenseTree 给定一个被删除了一个entry的叶节点L,如果剩下的entry少于m,则要进行节点合并,同时向上传播EI的变化。

  1. 令N=L,同时集合Q用来存放被删除的节点
  2. 如果N不是根节点,则查找N的父节点P,以及N在P中对应的entry\(E_N\);如果N是根节点,则要开始节点重插过程,见步骤6
  3. 如果节点N中剩下的entry数量小于m,则将\(E_N\)从P中删除,并将N加入集合Q
  4. 如果节点N并没有被删除,则调整\(E_N\)使其框住所有N中所有EI
  5. 令N=P,重复步骤2;即逐层向上传播变化
  6. 集合Q中的节点所包含的entry重新被插入R-tree中,来自叶子节点的entry直接调用insert过程即可,而来自非叶子结点的entry需要被插入对应高度层的节点中。

节点分裂

当一个节点上包含的entry数量超过M时,就会触发节点的分裂。节点分裂后,应当尽量避免一个查询需要访问多个节点的情况,而决定一个节点在查询中是否被访问的原因是该节点上的entry的MBR是否与查询区域向重合,所以应当是分裂后节点其对应的MBR尽可能的小。

穷举算法

将M+1个entry分为两组的所有情况穷举,并计算出所有情况的MBR值。显然这一方法复杂度过高。

平方复杂度算法

  1. 调用PickSeeds过程,选取两个组中的第一个entry。
  2. 如果所有的entry已经被分配,那么过程结束;如果有一个组G中的entry数量x不足m,且剩下的尚未分组的entry数量为m-x,则将这m-x个entry都分给组G,并停止过程
  3. 调用PickNext过程,在剩下的尚未分组的entry中选择一个entry进行分组;将其加入包含该entry后,MBR扩展最小的组

PickSeeds 在所有entry中,选择最不应该分为一组的两个entry,作为两个组的第一个entry

  1. 对于每一对entry \(E_1\)\(E_2\),计算归为一组后的无效性\(d=area(J)-area(E_1 I)-area(E_2 I)\),其中,J为包含\(E_1\)\(E_2\)的矩形。
  2. 选择d最大的一组

PickNext 首先选择归为不同组差别最大的entry进行分组(因为最后的entry很可能会根据补偿m的原则,不考虑分组造成的MBR扩展而直接进行分组)

  1. 计算所有entry归入不同组G1和G2后,MBR增长量\(d1\)\(d2\)
  2. 选择\(d1\)\(d2\)差别最大的entry
posted @ 2015-09-05 15:25 OllieO 阅读(...) 评论(...) 编辑 收藏