发明内容
为解决上述现有技术所存在的问题,本发明提出了一种程序执行方法,包括:
当对AVL树索引结点进行更新时,在日志缓存产生一条缓存日志,将属于同一结点的日志归为一个结点日志组;
当日志缓存被写满时,以结点日志组为单位进行组合,将缓存的日志写入Flash的日志存储区;
在对经过更新操作分散在日志存储区多个页记录内的日志进行遍历之前,在内存中建立结点日志查找表,记录结点和结点日志所在Flash页之间的映射关系;
对结点进行日志整合,将日志存储区中属于同一结点的所有日志解析合并为一个完整的AVL树结点,并写入到结点逻辑区中。
优选地,所述日志缓存和结点缓存位于嵌入式***内存中;日志存储区和结点逻辑区存储于嵌入式***的NAND Flash中。
优选地,所述日志存储区中索引结点以日志的方式进行存储,每次以页长度为单位进行写入;索引结点包含日志部分和逻辑部分,索引检索时通过结点日志查找表读取结点日志部分,并将日志部分和逻辑部分合并为结点完整的信息,将最近访问的索引结点缓存在结点缓存中。当结点缓存满时,根据结点访问次数、结点最近访问时间和从Flash中读取结点的代价来替换结点。
优选地,当日志缓存满时,将日志从日志缓存写入日志存储区采用以下步骤进行:
步骤1:按照n个结点日志组的大小降序排序得到序列S={s1…sn},如果单个结点日志组大于一页,将大于部分的日志写入日志存储区,剩余部分作为该结点日志组重新排序;
步骤2:取出S中第1个元素s1,即最大的日志组,写入虚拟的Flash页vp,更新该虚拟页剩余容量sp为sp-s1;
步骤3:取出S中第i个元素si,遍历已有的虚拟页vp,查找剩余容量sp大于si且sp-si最小的虚拟页,将该si写入该虚拟页并更新sp,如果没有满足条件的虚拟页,将该日志组写入新的虚拟页;
步骤4:i增1,重复步骤3,直到i=n;
步骤5:将所有的虚拟页vp写入Flash。
优选地,所述结点日志查找表,维护了结点和日志所在Flash页面之间的对应关系,该结点日志查找表初始化为一个固定大小的数组,每个数组元素维护一个结点链表,通过散列映射的方式将结点映射到数组的相应位置,通过结点日志查找表,该路径上的所有结点均通过散列表査出其在日志中的位置,如果日志页中含有同一结点的日志,则这些日志页组成该结点的日志链表,结点链表上每个元素都有一个指针指向其日志页组成的链表。
本发明相比现有技术,具有以下优点:
减少数据库更新时写NAND Flash的次数,保证索引的更新效率,和数据库的检索性能。
具体实施方式
下文与图示本发明原理的附图一起提供对本发明一个或者多个实施例的详细描述。结合这样的实施例描述本发明,但是本发明不限于任何实施例。本发明的范围仅由权利要求书限定,并且本发明涵盖诸多替代、修改和等同物。在下文描述中阐述诸多具体细节以便提供对本发明的透彻理解。出于示例的目的而提供这些细节,并且无这些具体细节中的一些或者所有细节也可以根据权利要求书实现本发明。
本发明提出一种高效的索引方法,该索引方法能够减少数据库更新时写NAND Flash次数,保证索引的更新效率,同时兼顾数据库的检索性能。图1是根据本发明实施例的程序执行方法流程图。本发明首先将数据库索引分为日志缓存、日志存储区、结点逻辑区以及结点缓存4个区域存储。
日志缓存和结点缓存位于嵌入式***内存中;日志存储区和结点逻辑区存储于嵌入式***的Flash中。
当每次对AVL树索引结点进行更新时,在日志缓存产生一条缓存日志,并将属于同一结点的日志归为一个结点日志组。当日志缓存被写满时,以结点日志组为单位进行组合,采用降序最佳适应方法将缓存的日志写入NAND Flash的日志存储区。
日志存储区中索引结点以日志的方式进行存储,每次以页长度为单位进行写入,更新效率高。
结点经过多次更新操作后,其日志分散在日志存储区的多个页记录内,检索时需要对所有日志页进行遍历,导致检索效率相对较低。因此,本发明在内存中建立结点日志查找表,记录结点和结点日志所在Flash页之间的映射关系,避免了读取单个结点日志而遍历日志存储区,从而提高了索引检索效率。
AVL树的检索特点是对树进行深度搜索,从叶结点获取最后的检索结果,共检索出L个结点(i为AVL树深度)。经结点日志查找表优化后,日志方式的结点检索代价取决于这L个结点的日志页总和,也就是这L个结点被更新的次数越多,检索效率越低。因此本发明设计结点逻辑区来进行索引存储。结点逻辑区中索引以完整的AVL树结点的形式存储,保存在一个Flash页上,本发明称该页为结点的逻辑页。在结点逻辑区中,索引的检索代价仅为读取i个结点的逻辑页的代价(i为AVL树深度)。由于索引采用日志方式更新,本发明进一步对结点进行日志整合,即将日志存储区中属于同一结点的所有日志解析合并为一个完整的AVL树结点,然后写入到结点逻辑区中,以提高索引的检索效率。由于日志整合是索引检索的额外开销,通过日志整合方法,权衡日志整合的开销和其带来检索性能上的提升,选择适当时机进行日志整合,以提高结点检索效率。
由于索引结点包含日志部分和逻辑部分,索引检索时需要读取两部分,通过结点日志查找表读取结点日志部分,并将日志部分和结点逻辑部分合并为结点完整的信息。为进一步提高结点检索效率,本发明设计了结点缓存来缓存最近访问的索引结点。当结点缓存满时,基于权值的缓存替换方法,通过权衡结点访问次数、结点最近访问时间和从Flash中读取结点的代价这3个因素来淘汰结点,减少从Flash读取未命中结点的总代价,从而提高检索效率。
1.索引更新
索引结点的更新包括结点内关键字或指针的***、删除和修改等操作,本发明对每次结点的更新产生一条日志,定义日志格式为:{type,node,time,key,dataptr},其中,type表示日志的操作类型;node标识该日志属于哪个结点;time为日志时间戳;key和dataptr分别表示结点的关键字和关键字指向的记录保存位置。对同一个结点的多次更新产生多条日志,不同结点的更新会随机交替,如果直接存储到日志存储区则分散在多个Flash页面,导致结点检索效率下降。因此,日志缓存定义了Flash页面整数倍长度的缓存空间,将属于同一个结点的所有更新日志归为一个日志组,当日志缓存满时以结点日志组为单位写入日志存储区,能在提高日志的写入效率的同时,提高日志存储区的査询效率。
当日志缓存满时,将日志从日志缓存写入日志存储区是一个典型的装箱问题,为达到利用最少的页存储单个结点日志组,本发明采用以下方法进行缓存日志的写入,方法描述如下:
步骤1按照n个结点日志组的大小降序排序得到序列S={s1…sn},如果单个结点日志组大于一页,将大于部分的日志写入日志存储区,剩余部分作为该结点日志组重新排序。
步骤2取出S中第1个元素s1,即最大的日志组,写入虚拟的Flash页vp,更新该虚拟页剩余容量sp为sp-s1;
步骤3取出S中下一个元素si,遍历已有的虚拟页vp,查找剩余容量sp大于si且sp-si最小的虚拟页,将该si写入该虚拟页并更新sp,如果没有满足条件的虚拟页,将该日志组写入新的虚拟页。
步骤4重复步骤3直到sn。
步骤5将所有的虚拟页vp写入NAND Flash。
2.结点日志查找表
为了快速索引结点日志,避免遍历整个日志存储区读取单个结点的日志,本发明在内存中建立结点日志查找表,维护了结点和日志所在Flash页面之间的对应关系。
结点日志查找表初始化为一个固定大小的数组,每个数组元素维护一个结点链表,通过散列映射的方式将结点映射到数组的相应位置,组成一个结点链表。结点链表上每个元素都有一个指针指向其日志页组成的链表,如果日志页中含有同一结点的日志,则这些日志页组成该结点的日志链表。
由AVL树方法可知,***和删除只在叶结点进行,所以,AVL树的检索都是经过一条从根结点到叶结点的路径,数据库检索时,必须逐一查找从根结点到目标叶结点这条路径上的所有结点。设AVL树的深度为L,日志存储区中所有日志页总数为N,读取一页代价为C,那么不通过结点日志查找表检索结点时需要对路径上的所有结点遍历一次日志存储区,设其检索代价为则Q1=L*N*C。
通过结点日志查找表,该路径上的所有结点均可通过散列表査出其在日志中的位置,设其检索代价为Q2,则Q2=∑(qi*C)(i=1-L),其中,qi为目标路径上单个结点的日志页数,显然Q2<Q1,所以,结点日志查找表优化了日志存储区中结点的检索效率。
3.结点逻辑区和日志整合
在结点逻辑区进行结点检索时,同样AVL树经过一条从根结点到叶结点的路径。而结点逻辑区中结点以完整AVL树结构形式存储,父结点可直接索引到子结点,设结点检索代价为Q3,则Q3=L*C明显小于Q2。因此,本发明提出日志整合方法来整合日志存储区中结点日志到结点逻辑区,以提高索引检索效率,整合后AVL树所有结点的分布方式为:
(1)结点只存在于日志存储区;
(2)结点只存在于结点逻辑区;
(3)结点经过日志存储区到结点逻辑区的整合后又被更新,即结点记录存在于结点逻辑区和日志存储区两者中。
方式(1)只发生在结点不满足整合条件,从未被整合进入结点逻辑区,这种结点需要检索日志存储区;方式(2)发生于日志刚被从日志存储区整合进入结点逻辑区,这种结点只需要检索结点逻辑区;而方式(3)是日志被整合进入结点逻辑区后,还对该结点进行更新操作,需要先从结点逻辑区检索到该结点,再通过结点日志查找表从日志存储区中检索结点更新,获取最后检索结果。显然,日志整合的目的是将方式⑴和方式(3)均变为方式(2)提高检索效率,但同时也需要付出整合开销。
日志整合开销是将路径上L个结点均整合到结点逻辑区,相当于写L个页的代价,设写一页的代价为C,日志整合的开销为M,则M=L*C。日志整合方法通过权衡日志整合的开销和其带来检索性能上的提升,选择适当的时机进行日志整合。
日志整合方法采用滑动窗口的方式进行结点检索代价的统计,并结合最优在线策略即收支平衡策略选择合适的时机进行日志整合。描述如下:
结点日志检索代价采用滑动窗口的方式进行统计,滑动窗口的总长度为w,并等分为m个子窗口,以w/m步长沿时间轴滑动,毎个子窗口统计结点的日志检索代价为r=∑Q2;
当子窗口统计时间结束时,将窗口w内m个子窗口结点检索代价r求和,得到窗口w内结点的日志检索总代价R=∑ri(i=1…m);
由于日志整合后,结点检索不需要再对结点日志进行检索,因此其收益即为结点的日志检索总代价,日志整合的支出即日志整合开销,采用收支平衡策略,比较结点的当前日志检索总代价R和结点日志整合的开销M,如果R>M则将该结点进行日志整合。
完成结点该次整合后,丢弃最早子窗口的统计信息,将滑动窗口沿时间轴前进w/m,继续下一个统计周期。
4.结点缓存
由于数据库的访问具有空间聚集性,一段时间内数据库对某些索引结点会进行频繁访问或更新,本发明在内存中开辟结点缓存,暂存这些最近经常被访问的结点,从而提高了结点检索效率。
由于结点缓存大小固定,当缓存满时,需要采用缓存替换方法淘汰其中的某些结点。设在一段时间内依次对结点序列b1,b2…bn进行访问,其中未能在缓存命中的结点序列为b1’,b2’…bm’。所以,对该结点序列的访问代价为从NANDFlash读取所有未能命中结点代价的总和,即:
Ctotal=Cb1’+Cb2’+…Cbm’
其中,Cbi’表示从NAND Flash读取结点bi’的代价。
从以上公式可以看出,为了尽量减少结点序列的访问代价Ctotal,缓存替换方法应尽量提高结点的命中率,减少未命中结点个数,同时选學从Flash读取代价小即Cbi’小的结点替换出缓存。针对缓存结点替换问题,本发明提出基于权值的替换方法。描述如下:
将缓存所有的结点组织成一个链表,并且给每一个结点b赋予一个权值W,W的计算公式如下:W=Cb*Cnt(b)/(Tnow-Tlast)
其中,Cb为从Flash读取结点的代价;Cnt(b)为结点b的访问次数;Tnow为当前时间;Tlast为结点最近一次的访问时间,所以,权值函数综合考虑了结点的读取代价、结点的访问次数和最近的访问时间;
根据每个结点的权值W进行排序,当结点缓存满时,选择权值最小的结点替换出缓存区。
因此,该方法替换访问次数少和最近没有访问的结点,保证了缓存的命中率,同时淘汰读取代价小的结点,减少了整个结点序列的访问代价,从而使结点缓存最大程度提高结点的检索效率。
综上所述,本发明根据Flash的读写特点,提出一种应用于NAND Flash数据库的索引方法。该方法釆用日志记录索引更新,删除冗余日志,提高了索引的更新效率。实验结果表明,在检索和更新效率上有明显提高。
显然,本领域的技术人员应该理解,上述的本发明的各模块或各步骤可以用通用的计算***来实现,它们可以集中在单个的计算***上,或者分布在多个计算***所组成的网络上,可选地,它们可以用计算***可执行的程序代码来实现,从而,可以将它们存储在存储***中由计算***来执行。这样,本发明不限制于任何特定的硬件和软件结合。
应当理解的是,本发明的上述具体实施方式仅仅用于示例性说明或解释本发明的原理,而不构成对本发明的限制。因此,在不偏离本发明的精神和范围的情况下所做的任何修改、等同替换、改进等,均应包含在本发明的保护范围之内。此外,本发明所附权利要求旨在涵盖落入所附权利要求范围和边界、或者这种范围和边界的等同形式内的全部变化和修改例。