1、随机跳跃索引:一种支持随机插入的可信赖索引摘 要: 跳跃索引是一种可信赖性索引,但只能为严格单调递增的序列建立索引,不能处理非顺序序列。为了解决这个问题,本文提出了一种新的索引,它可以对任意顺序的序列建立索引,并且依然保证索引的可信赖性。通过在原有跳跃索引结构加中入左侧跳跃指针的方法,索引节点可以根据待加入节点值的大小将其纳入自己的左侧或右侧指针以处理随机序列;索引结构中的每一个节点到根节点的路径固定且唯一,保证了索引的可信赖性。实验结果和理论证明都表明该索引是可以处理随机序列的可信赖索引,相对原有索引,索引建立复杂度明显降低且具有相同的查找复杂度。本文的创新之处是在保证索引的可信赖性的基础上
2、解决了跳跃索引不能为随机序列建立索引的问题。关键词: 可信赖性;倒排表;索引;B+ 树;检索;算法A Trustworthy Index for Inserting Random SequencesAbstract: Jump Index is a kind of trustworthy index which can only build index for strictly monotonically increased sequences rather than unordered sequences. To solve this problem, this paper proposed
3、 a novel index supporting building index for random sequences, without losing the trustworthy of jump index. By adding left pointers on the node of jump index, the candidate node in random sequences can be indexed into one of the left or right pointers of a node in the index. The left jump pointers
4、are used to index nodes with less value than current nodes value, while right jump pointers point to those nodes with higher value. Every node in the index has the unique and permanent path from root node, which ensures the trustworthy in the index. Experiment results and proofs in this paper show t
5、hat the index is trustworthy and supports indexing for random sequences, also it has more efficiency of building index and same complexity of search compared with jump index. The contribution of this paper is that the new index with trustworthy solve the problem that jump index cannot insert and bui
6、ld index for random sequences.Key words: Trustworthy;Inverted Index; B+ Tree; Retrieval; Algorithm1 引言在商业运作以及一些重大事务的关键决策过程中,电子邮件、会议记录、财务状况以及项目计划书等诸如此类的文件起着关键作用,属于重要而且基本的信息。因此这些信息必须以一种可信赖(trustworthy )的方式保存,从而使它们不能被恶意的删除或者篡改,并且易于访问。然而,随着文档被大量的电子化这些信息也变得更容易被篡改、删除,且不留任何痕迹。因此,确保数据信息的易于访问性、准确性、可靠性和不可抵赖性已
7、经成为势在必行的趋势。在这种趋势的推动之下,WORM(Write Once Read Many 一次写入多次读取)存储设备便成了此类信息存储的主要方式。但是在 WORM 保存数据并不能充分保证数据的可信赖性 1,例如,它不能为以前所发生的事件提供不可抵赖性证据。此外,即便是数据保存在 WORM 设备中,如果访问这些数据的索引可以被改动的话,数据还是可以被隐藏或者删除的。例如,索引中指向某一数据的指针被删除或者改动后指向另一数据,这时原来的数据会再也访问不到了。因此,仅仅是数据以可信赖的方式保存是不够的,索引本身也要以可信赖的方式保2存。为了解决可信赖性索引的问题,近几年的研究也提出了一些方法,
8、 其中跳跃索引(Jump Index) 2是目前解决索引可信赖性最好的方法,但它要求被索引文档 ID 有序递增,不支持以随机插入的方式建立索引。本文针对跳跃索引不能支持以随机插入的方式建立索引的不足,设计了新的跳跃索引结构,该索引支持被索引文档的非顺序插入,而且具有和原有索引相同的可信赖性。2 相关工作针对索引的可信赖性,目前的一些研究中提出了化石索引(fossilized index) 1的概念,主要思想是不允许对索引进行操作。Generalized Hash Tree(GHT)1,3,4就是一种化石索引,但这种方法对数据信息的结构要求严格,不具有通用性。它可以根据数据的属性提供精确查找,适
9、用于结构化的数据。但是大部分商业数据,例如邮件内容、会议记录、备忘录等都是非结构化或半结构化的,这类信息查找最适合的方法是关键词查找。基于关键词的查找最典型的方法就是倒排表(Inverted Index)5,6。Jump Index 就是在每一条记录的倒排表(Posting Lists) 7,8,9中以 Jump Index 方式建立索引。该索引的建立是为了提高不同倒排表之间的合并和连接 (Merge and Join)2操作。图 2 中是 Zigzag Join2,10算法,它可以将两个倒排表以时间复杂度 合并与连接, 分别为)(21nO21,n两个倒排表的长度,是一种效率很高的算法。Jum
10、p Index 就是为了支持 Zigzag Join 算法中的 FindGeq()方法。图1(a)中是 Jump Index 跳跃索引的节点的结构, Jump Index 每一个节点保存着倒排表中文章 ID,跳跃指针指向下一个节点。例如, 节点的第 个跳跃指针指向节点 , 。Jump Index 的结构保证了索引lil12iil中从根节点到任意一个节点的路径是唯一的,这就确保了索引的可信赖性。但是,Jump Index 要求待建立索引的序列是严格单调递增的,这样的约束条件为 Jump Index 带来了很大的局限性。例如,对一个随机的序列首先要对其排序后才能建立索引,之后,如果新的序列到来只能
11、将原有序列与新序列合并排序后重新建立索引,对较小的序列来说尚且可行,但是对非常大的序列来说,满足这种约束条件后再建立索引所付出的代价是非常大的。图 1(b)的例子中,序列 11, 2,5,7,15满足约束条件,可以插入到索引中;序列 28,9,14 不满足约束条件,因为 9 和 14 要插入的位置已经被 10 和 15 占据。遇到这种情况,Jump Index 只能将两个序列合并为1,2,5,7,8,9,10,14,15后重新建立索引。I D0 1 2. . . N2log跳跃指针10 1 2 3 4跳跃指针跳跃指针20 1 2 3 450 1 2 3 41 00 1 2 3 4跳跃指针 1
12、50 1 2 3 4跳跃指针70 1 2 3 4跳跃指针输入序列 1 : 1 , 2 , 5 , 7 , 1 0 , 1 5 输入序列 2 : 8 , 9 , 1 4 跳跃指针(a) Jump Index 跳跃索引的节点结构 (b) 索引的插入过程图 1:Jump Index 跳跃索引结构与插入过程3Z I G Z A G ( l i s t 1 , l i s t 2 )1 : t o p 1 l i s t 1 . S t a r t ( )2 : t o p 2 l i s t 2 . S t a r t ( ) I n i t i a l i z e t h e i t e r a t
13、 o r s t o p o i n t t o l i s t h e a d s 3 : l o o p4 : i f ( ( t o p 1 = l i s t 1 . E n d ( ) ) O R ( t o p 2 = l i s t 2 . E n d ( ) ) ) t h e n5 : r e t u r n6 : e n d i f7 : i f ( ( * t o p 1 ) = 0 , s u c h t h a t s - 2 ( j + 1 ) k ) 2 5 : F i n d i = 0 , s u c h t h a t i s + 2 ( i ) k ) 7
14、 : F i n d j = 0 , s u c h t h a t s - 2 ( j + 1 ) = 0 , s u c h t h a t s + 2 ( i ) = k ) 2 : i f ( s = = k ) 3 : r e t u r n s ;4 : 5 : F i n d j = 0 , s u c h t h a t s - 2 ( j + 1 ) = k c o u l d b e f o u n d b y f o l l o w i n g j t h l p t r ,/ / r e t u r n t h e F i n d G e q R e c ( k , *
15、 l p t r ) o f t h e f i r s t n o n - n u l l l p t r1 6 : j = j - 11 7 : w h i l e ( j = 0 ) 1 8 : i f ( s . l p r t j ! = N U L L ) 1 9 : t = d o c u m e n t I D a t s . l p t r j 2 0 : a s s e r t s - 2 ( j + 1 ) = 0 , s u c h t h a t s + 2 ( i ) = k c o u l d b e f o u n d b y f o l l o w i n g
16、 i t h l p t r ,/ / r e t u r n t h e F i n d G e q R e c ( k , * r p t r ) o f t h e f i r s t n o n - n u l l r p t r3 8 : i = i + 13 9 : w h i l e ( i = k1 : r e t u r n F i n d G e q R e c ( k , t h e r o o t n o d e i n t h e r a n d o m j u m p i n d e x )图 4: Random Jump Index 随机跳跃索引的基本算法3.2
17、复杂度分析为了清晰的说明随机跳跃索引的复杂度首先给出下列命题,然后证明之。7命题 1:设 是算法 Lookup( )执行过程中循环执行第 7 或 20 步所得 和 的序列,则 序列中ji,kijji,1。ji证明:在随机跳跃索引中执行 Lookup( )依次跳过的文章 ID 序列为: , 为 Random Jump Index 中kjs,11的根节点。在查找 的过程中从 跳到 会出现以下四种情况:(I ) ,(II) ,(III) k1s2 k22s,(IV) 。现在分别对这四种情况证明:( I) ,由算法 Lookup( )第 20 步可12sk2s1 k得 (a),因为 的右指针 指向 ,
18、所1ii 1s1i2s以 , (b)。同理得到 (c)。由(a) 和(c)得到211iiss2i122iisk(d)。再由(b)和(d) 得 。因此 。(II) ,由算法21ii 112iiiss2skLookup( )第 20 步可得 (a),因为 的右指针 指向 ,所以k1iiks 2s, (b)。由于 , 是 的左指针,且121iis12i 2ski(c)。由(a)和(c)得到 (d)。再由(b)和(d) 得2iik 1iis。因此 。2121 iiiiss21i(III) ,由算法 Lookup( )第 7 步可得 (a),因为 的左指针 指向 ,kk112iisks1s1i2s所以
19、, (b)。同理得到 (c)。由(a) 和(c)得到11iiss 12is 22ii(d)。再由(b)和(d) 得 。因此 。( IV) ,由算法21ii 11iiis11skLookup( )第 7 步可得 (a),因为 的左指针 指向 ,所以k11iisks 2s, (b)。由于 , 是 的右指针,且11iis21i 2ski(c)。由(a)和(c) 得到 (d)。再由(b)和(d) 得22iisk 12iis。因此 。以上四种情况下均有 ,同理可以证明 ,11iiis 2i1i jji13最后得出 。证毕j由上面的证明可以看出 Lookup( )执行过程中的循环次数不会超过 ,而 ,因此
20、最多跳k1i)(log2k8跃 步就可以找到 。算法 Insert( )和 FindGeq( )时间复杂度也为 。如果 为所有)(log2kkkk)(log2kON文章的总数,以上算法的最大时间复杂度为 。因此,可以得出这种随机跳跃索引的查找性能是和(log2NO原有跳跃索引性能是一样的。3.3 随机跳跃索引的可信赖性跳跃索引的优势在于它保证了索引中数据的可信赖性,即数据不能被改动或隐藏,数据的路径唯一且固定不变。而这些特性是由跳跃索引的两条性质保证的,随机跳跃索引具有和跳跃索引相同的可信赖性,为了说明这一点,下面证明它也具有跳跃索引的两条性质。命题 2:当文章 ID 插入到倒排表的随机跳跃索
21、引中之后,该文章 ID 总是可以被成功的查找到。证明:在执行 Insert()时,数据是被写在 WORM 设备上的,所以数据在写入之后是不会被改动的。上一节中的序列 对 Lookup()是唯一的,因此插入的数据总是可以被找到。证毕jii1命题 3:设 是一个在倒排表中的文章 ID。如果 ,那么 FindGeq( )返回的值不会大于 。vvkkv证明:设 是随机跳跃索引的根节点。此时有三种情况:(I) (II) (III) . 在0s vs00ssk0分别证明之前,设 在索引中的跳跃指针序列为 (例如,执行 Lookup( )所得序列 ) 。同voj,1 oj,1样,设 FindGeq( )返回
22、值 的序列为 。klpi,1(I) ,首先证明 。在第一次调用 FindGeqRec(),由第 28 步得到 ,因为 。vs0j 1jivk如果 通过了第 29 和第 33 步的检查,那么 , 。如果上两步都为假,那么 FindGeqRec()将执行第i i11j39 步。由于 在索引中,s.rptr 不会为 NULL,所以 , , 。这时又有两种情况:(i) v1ii1j这种情况下, 因为 。 (ii) 。此时直接调用 FindGeqRec()。1jilvsslji11200(II) ,首先证明 。第一次调用 FindGeqRec(),由第 5 步得到 ,因为 。如0skji 1jvk果 通
23、过了第 6 和第 11 步的检查,那么 , 。如果上两步都为假,那么 FindGeqRec()将执行第 17i 11ji步。由于 在索引中,s.lptr 不会为 NULL,所以 , , 。这时又有两种情况:( i) v1j ji1ji这种情况下, 因为 。 (ii) 。此时直接调用 FindGeqRec()。1jivlvslji10012(III) ,由(II )得 FindGeqRec( )返回值 ,又因为 ,所以 。sk0 k0lvs0l9以上三种情况下都有 FindGeqRec( ) 。证毕kv命题 3 保证了在连接两个倒排表时没有文章 ID 会被隐藏。如果文章 ID d 在两个倒排表中
24、都出现,执行zigzag join 算法时从表中最小的值开始调用 FindGeq(),性质 3 可以保证在返回 d 之前,FindGeq() 返回的值不会大于它。换言之,d 最终被两个倒排表中的 FindGeq()返回,并且出现在最终结果当中。这两条性质保证了随机跳跃索引与跳跃索引具有相同的可信赖性。3.4 广义的随机跳跃索引索引的深度是影响查找速度的主要因素。在文章 ID 非常多时,例如 、 甚至更大,减小索引深度能3264明显减少查找次数。为此,可以用 作为底数, ,不仅仅以 2 为底数。 。每个节点的左右跳跃指针个数B为 ,跳跃指针用参数 表示,其中 , 。如果 为当前节)(log1(N
25、B),(ji )(log0NiBj10s点,右指针 指向 ,那么 ;左指针 指向 ,那么,ji1s iijs)1(10,i。图 5 中的例子是以 3 为底数, ,文章 ID 总数 。节点 13 的iijs0)( 36右跳跃指针 指向 16,因为 ,同理右跳跃指针 指向 53,因为, 11)(63)2,(;13 的左跳跃指针 指向 7,因为 。321512, 137用广义的随机跳跃索引,Insert()、Lookup()和 FindGeqRec()算法的时间复杂度均为 。)(logkOB1 3(0,1)(0,2)(1,1)(1,2)(2,1)(2,1)(1,2)(1,1)(0,2)(0,1)(2
26、,2)(3,1)(3,2)(3,2)(3,1)(2,2)1 4 1 6 2 2 3 1 5 37 1 0 1 1 1 24图 5:广义的随机跳跃索引4 性能评估本节首先对 Random Jump Index 的索引大小做出分析;然后比较 Random Jump Index 与 Jump Index 两种索引在建立时,随机插入与严格单调递增插入的比较次数,最后对这两种索引的查找性能作出比较。影响这些性能的关键变量有底数 ,文章 ID 的总数 。BN在对总数为 的文章 ID 集合建立随机跳跃索引时,索引的大小可由下面的公式表示:N,其中 为一个跳跃指针的大小,通常为 4 个字)(log1(2epI
27、ndex siziSiz psiz节, 为节点元素值的大小,通常为 4 或 8 个字节。索引大小 与 和 成正比。在实际应用中s IndexSBN对不同的 , 可以根据查找的查找效率与存储效率所相应调整。B下面对比二者建立索引时的效率。Random Jump Index 可以连续处理多个文章 ID 序列,而 Jump Index 只能处理一个文章 ID 序列,如果有新的序列到达, Jump Index 只能将原有序列与新序列按照递增顺序合并后,毁掉以前的索引重新建立索引;对于 Random Jump Index 则只需要将新序列插入到原有索引即可。显然,在处理多10序列时 Random Jum
28、p Index 要大大优于 Jump Index。现在只对比处理单个序列时二者的复杂度:设 为10,Nl随机序列,Random Jump Index 继续将该序列的 个元素依次插入的索引中即可,总的比较次数为N;对于 Jump Index 则需要将该序列排序后再依次插入索引,当该序列有序时它的比较次数与也是NkB1log,当序列无序时调整次序需要 次比较,所以 Jump Index 对该序列建立索引总比较次Blog数为 。可见对单个序列建立索引时,Random Jump )ll)(!1log! 121 NkNkBIndex 效率也高于 Jump Index。最后,对比两者的查找效率。Jump Index 查找时,根节点始终为序列中最小的节点, ,最大比1minl较次数为 。Random Jump Index 查找时比较次数与根节点的值 有关,而 等于该序列的期望NBlog rotlrot值, ;Random Jump Index 查找时的平均比较次数为 。命题 12/,10lErt 2/lgNB决定了二者的最坏查找效率相等,但平均查找效率 Random Jump Index 要优于 Jump Index。(a)索引大小对比 (b)建立索引的效率对比(c)查找效率对比图 6:随机跳跃索引的性能试验结果