RTree研究学习~

来源:互联网 发布:公司网络规划 编辑:程序博客网 时间:2024/05/16 08:43

最近一个新的任务 要做一个RTree索引 速度查了一些东东 当然最经典的还是Guttman的那篇paper~讲解的很详细 :) 明天开始研究算法吧 时间比较紧 :(

下面是对Guttman paper的部分翻译 不一定准确 :) 偶英文比较烂 :)

<!-- /* Font Definitions */ @font-face{font-family:宋体;panose-1:2 1 6 0 3 1 1 1 1 1;mso-font-alt:SimSun;mso-font-charset:134;mso-generic-font-family:auto;mso-font-pitch:variable;mso-font-signature:3 135135232 16 0 262145 0;}@font-face{font-family:"/@宋体";panose-1:2 1 6 0 3 1 1 1 1 1;mso-font-charset:134;mso-generic-font-family:auto;mso-font-pitch:variable;mso-font-signature:3 135135232 16 0 262145 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal{mso-style-parent:"";margin:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:inter-ideograph;mso-pagination:none;font-size:10.5pt;mso-bidi-font-size:12.0pt;font-family:"Times New Roman";mso-fareast-font-family:宋体;mso-font-kerning:1.0pt;} /* Page Definitions */ @page{mso-page-border-surround-header:no;mso-page-border-surround-footer:no;}@page Section1{size:612.0pt 792.0pt;margin:72.0pt 90.0pt 72.0pt 90.0pt;mso-header-margin:36.0pt;mso-footer-margin:36.0pt;mso-paper-source:0;}div.Section1{page:Section1;}-->

 

空间数据经常是多维的,并不能用一些点来简单的表示。例如地图里面的街道、村庄等。对空间数据的一个典型操作是查找某个区域的所有目标(例如查找中关村大街上所有的餐馆等)。

       对空间数据建立索引是一种好的想法,但传统数据库的一维索引并不适合对多维数据的查找。例如hash等结构也不适合,因为搜索的时候有一定的范围。而类似B-Tree的一些结构不能实现对多维数据的查找。

       R-Tree索引:

       R-Tree索引是一个高度平衡的树,在它的叶节点存放指向数据的指针。并且RTree能够保证对一个空间数据的搜索只需要访问很小一部分的node

       空间数据库包含了很多tuple,这些tuple代表了空间数据。每一个tuple有一个唯一的标识(ID),这样可以访问到某个tupleRTree中叶节点包含的索引记录的形式是(I , tuple-identifier),这里的id指向数据库中的一个tupleI表示一个n维的矩形,这个矩形是一个boundingbox,用来涵盖被索引的空间数据对象。

       I =(I0, I1, I2, …., In-1)n表示维度,Ii是一个闭区间[a,b],用来表示对象在第i维中的长度。另外,如果a或者b是无穷的话,表示该对象延伸到了无限远处。

       非叶节点的形式是(I,child-pointer)child-pointer 是子节点的地址;I是覆盖了其所有子节点的矩形。

       RTree中,每个节点所有的子节点的数目是有限制的,假设每个节点最多拥有M个子节点,m<=M/2.RTree有以下的属性:

       1).除了根节点外,每个节点所拥有的子节点数要在[m, M]间。

       2).对于每一个叶节点的索引记录(I, tuple-identifier) I是最小的能够包含n维数据对象的矩形。

       3).对于每一个非叶节点的索引记录(I,child-pointer)I是最小的能够包含所有子节点的矩形。

       4).根节点至少有2个子节点

       5).所有的叶节点都在同一层

        

 

      图显示不出来了 :(

   

查找:

    查找是从根节点开始(实现的时候需要从任意节点都可以)。查找时,可能会有多个子树被访问。

    假设根节点是T;索引entryE表示;EI表示这个索引的矩形;Ep表示tuple-identifier或者child-pointer.

 

搜索算法(search)给定一个RTree,找出所有的索引记录,这些索引的矩形与搜索矩形S(这个搜索矩形是指定的,可以考虑为一个参数)有重叠的部分。

 

    S1.搜索子树。如果T不是叶节点,检查每一个entry,看EI是否与S 有重叠,如果有,则递归调用search,用于搜索以EP为根节点的子树。

    S2.搜索叶节点。如果T是叶节点,检查所有的entry E,看EI是否与S有重叠,如果有,E就是一个满足条件的entry.

 

插入:

为一个新的数据tuple插入一个索引记录,是指在叶节点增加一个新的索引记录,如果这个节点溢出(子节点数目大于M),则将这个节点进行split,然后更新树。

 

插入算法。(insert)

       I1. 为新记录找一个合适的位置。调用ChooseLeaf来选择一个叶节点L用于存放E

       I2. 将记录增加到叶节点。如果L有空间(既它的子节点个数小于M),将E放大L中。否则,调用SplitNode获得LLL(其中LLL是将L进行split后的结果,这2个新节点中包含了L中原来的所有节点和新节点E

       I3. 在节点L上调用AdjustTree。如果进行了splitLL也作为一个参数。

       I4. 如果节点的split导致了根节点的split,则创建一个新的根节点,这个节点的子节点是原来的根节点和split后的节点。

 

选择叶节点算法。(ChooseLeaf)选择一个叶节点,用于存放新的索引记录E

       CL1. N作为根节点

       CL2. 如果N是叶节点,则返回N

       CL3. 如果N不是叶节点,选择N的子节点F。选择的F具有这样的性质。如果将EI包含到FI中,FI的面积增加的最少。

       CL4. N作为子节点,重复调用CL2CL3

 

调整树算法。(AdjustTree)从叶节点L到根节点,进行调整。

       AT1. N=L,如果L之前进行过split,令NN作为另外一个新的节点(LL

       AT2. 如果N是根节点,停止

       AT3. 调整父节点的覆盖矩形。让P作为节点N的父节点,并且让EN作为PNentry。调整ENI,使其能够恰好(不要有太多没用的空间)包含矩形N中所有的entry

       AT4. 如果L进行了split,创建一个新的entry ENN ENNP 指向NN ENNI包含NN中所有的矩形。如果N的父节点P有空间,则将ENN放入到P中;否则,调用SplitNode算法,将P进行split,得到PPP,他们包含了ENNP中原来的所有entry

       AT5. N=P  NN=PP(如果有split),重复从AT2的过程。

 

节点split算法。

       为了在一个已经满的节点中增加一个新的节点,必须将这个节点进行splitSplit就是将这M+1个子结点从新进行分配到2个新的节点中。进行split后的结果应该这样,在后面对某个节点的搜索中,尽可能不要在两个新父节点中都进行搜索(既split后,尽量保证原来的每个节点只属于其中的某一个父节点)。

在搜索中是否搜索某一个节点,是有这个节点的矩形是否和待搜索矩形有重叠来决定的,因此,split后的两个矩形的覆盖面积应该最小。

 

Split算法:

       一是穷举法。显然不合适。

       二是时间复杂度为平方的近似算法。这个算法试图找到一个面积和最小的split,但不保证会找的到。算法先从M+1enrty中挑出两个作为2个新group的第一个元素。这两个entry的选择是这样的:如果将这两个entry放到同一个group的话,所需要的矩形面积最大。然后每一步再对剩余的entry进行分组,每个元素放到一个group中。在每一步中,计算将每个entry放入到每个group后的面积增加值,然后将差值最大的entry进行分配。

平方级split:Quadratic SplitM+1entry分配到两个group中。

       QS1. 为每个group选择第一个entry。利用算法PickSeeds来选择最初的两个entry,并将他们分配到不同的group中。

       QS2. 检查是否结束。如果所有的entry都已经分配了,停止。如果一个group拥有的entry比较多,那么要将剩余的entry分配到另外一个group(为了保证>=m)

       QS3. 调用算法PickNext来将下一个entry进行分配。将该entry分配到面积增加最小的组中。重复QS2.

 

选择第一个元素算法(PickSeeds)

       PS1. 对于每一个entry E1 E2,计算包含E1IE2I的矩形J的面积,令d=area(E1I)-area(E2I)

       PS2. 选择d最大的作为初始元素。

 

算法PickNext

       PN1. 对于每一个没有分配到group中的entry E计算d1=EI放到group1中后的面积增加值。d2类似。

       PN2. 选择d1d2差值最大的entry

 

还有其他工作需要进行 加油~