论文阅读——Updatable Learned Index with Precise Positions(VLDB‘21)

1.介绍:

索引在现代数据库引擎中起着至关重要的作用,可以加速查询处理。“学习索引”的新模式显著改变了DBMS中索引结构的设计方式。关键的想法是,learned index把索引结构当成是一种预测模型,给定一个key,预测这个数据在数据表中的位置。最近关于学习索引的研究为构建数据的索引开辟了一条新的途径。给定一个数据集,学习索引利用机器学习模型来学习数据分布并预测数据集中查找键的位置。它可以通过使用训练数据集的累积分布函数(CDF)通过监督学习技术来实现。由于模型对于预测位置可能不准确,学习索引需要在预测位置周围的有界范围内搜索查找关键字。

2.论文动机

论文研究的出发点是在索引查找的最后一步,模型可能是不准确的,预测错误之后,需要在一个误差范围内进行一个线性或者二分查找,这在误差比较大的时候,需要占用比较多的时间。如下图所示的,B+树和Learned index的示意图,B+tree 是以页为单位储存,根据key和不同页的最小值进行比较,确定key存储在哪个确定的页中,然后需要在这个页里面进行二分查找,找到目标数据。Learned index预测到一个position,然后在这个模型的error_bound之间进行顺序或者二分查找。

这篇论文最大的优势就是将这个最后一步给消除,模型预测一定是准确的,如果预测的位置是需要查找的key,直接找到,如果不是,说明key不存在,不需要进行一个范围查找。
论文阅读——Updatable Learned Index with Precise Positions(VLDB‘21)_第1张图片

3.论文挑战

LIPP的核心思想就是消除不准确的预测,模型的预测都是准确的,这样就可以减少节点内部查找的开销,以及插入的时候元素移动的开销。

这样带来两个问题:
1.两个不同的key,如果模型预测到一个地方应该怎么处理,比如插入元素的时候,发现模型预测的位置已经有元素存在。
论文的处理方法是再创建一个node,其实也就是在创建一个分类器进行区分。
2.第二个挑战是第一个方法导致的,如果这样一直创建分类器的话,会导致节点很多,树高度很高。

4.索引结构

下面是LIPP的结构,每个节点包括一个模型M,一个记录数组E,以及一个bitmap表示记录的类型

记录的类型包括三种,
1.NULL,表示当前记录为空,可以用来存储key
2.DATA,数据记录,存储key以及数据
3.NODE,存储的是一个指向下一层节点的指针,就表示当前层无法完全将元素分类开,需要下一层继续进行分类。
论文阅读——Updatable Learned Index with Precise Positions(VLDB‘21)_第2张图片

查找操作

从根节点开始,将key输入模型M,得到一个position,如果这个记录对应的是node的话,就根据node指针指向下一层节点,如果这个记录是DATA的话,就说明找到位置了,判断一下这个位置存储的key和当前查找的key是否相等,相等返回true,否则返回false。
没有必要在节点内部进行额外的查找,所以查找的时间复杂度为O(h),其中h是树的高度。
论文阅读——Updatable Learned Index with Precise Positions(VLDB‘21)_第3张图片

插入操作

跟刚才查找的操作一样,首先将key送入根节点的模型进行预测,如果预测到的位置是node,那么就继续往下查找,如果找到的位置是NULL,那么就将数据放入到当前位置,并且设置当前节点类型为DATA;如果当前位置是DATA,表示已经有数据存储了,发生了冲突,那么需要建立一个新node,将这个位置原先的数据以及待插入的数据,一起放入新生成的node中,构建新的分类模型进行区分。

为了防止树无限的往下生长,因为如果每冲突一次就往下长一个节点,那么树的高度可能会非常高,影响性能,所以作者提出了一个调整的操作。
论文阅读——Updatable Learned Index with Precise Positions(VLDB‘21)_第4张图片
###5. 调整操作
调整操作的目的就是控制树的高度,因为查找、插入操作的时间复杂度都是和这个高度直接有关。
针对调整,作者主要从两方面,什么时候调整和怎么调整进行介绍,作者提出两个评判标准,判断是否触发调整操作。
怎么调整,作者收集当前节点以及其子树的所有数据,进行子树重建,再用新建成的子树替换掉原来的位置。

何时调整

第一个条件是element_num是build_num的beta倍,其中element_num是元素总数,build_num表示的是上次adjust操作后节点的记录数量,
第二个条件是conflict_num大于alpha*(element_num-build_num),其中conflict_num表示结点产生冲突的次数

第一个公式表示只有在当前节点的记录数量是上次调整时的beta倍才考虑是否再次调整,该标准有效地降低了调整频率。Beta通常设置为2
第二个公式表示新插入的记录中产生冲突的比例,用于控制树的高度,alpha通常设置为0.1
论文阅读——Updatable Learned Index with Precise Positions(VLDB‘21)_第5张图片

这是一个示意图,当一个新key到达的时候,根据插入算法,插入到第三层的节点中,插入完成之后需要判断整个路径上的节点是否需要进行重建,根据刚才的规则,我们可以发现第二层的节点,满足所有调整的条件,这里按照默认设置beta为2,alpha为0.1,进行调整操作,将节点以及其子树上的所有数据收集起来,建立一个新的节点,新的分类器,将数据分隔开。
论文阅读——Updatable Learned Index with Precise Positions(VLDB‘21)_第6张图片

怎么调整

怎么去调整,主要的方法就是子树的重建的过程。
作者提出一个算法BuildPartialTree,先创建一个足够放置所有数据的节点,然后根据FMCD算法,根据数据求出最适合的一个模型,可以将数据更好的分隔开。这个FMCD算法是作者自己提出来的,其实是一个类似遍历的方法,寻找冲突最少的模型,穷举冲突为0,1,2,3,只要找一个最小冲突 模型,就使用它。找到模型之后,就根据这个模型将刚才的数据放置到指定位置,如果这时候还产生冲突,递归的调用算法,创建新的子树。
论文阅读——Updatable Learned Index with Precise Positions(VLDB‘21)_第7张图片

6.实验

最后是实验部分,不同颜色表示的是不同的对比算法,横坐标表示的是不同的数据集,纵坐标表示的是算法的吞吐量,不同图表示的是在不同的负载条件下,只读、读多写少、写多都少、只写的四种情况,可以看到LIPP在不同的负载条件、不同的数据集中,效果都是最好的。
论文阅读——Updatable Learned Index with Precise Positions(VLDB‘21)_第8张图片
作者进一步比较了read-heavy和write-heavy负载下的索引大小,可以看到在某些情况下,不如ALEX,整体上还是不错的表现。
对于范围查找,LIPP的优势不大,大家都差不多
对于BulkLoad,LIPP和B+tree相当,比ALEX、ART优秀。

论文阅读——Updatable Learned Index with Precise Positions(VLDB‘21)_第9张图片

你可能感兴趣的:(数据库,算法,人工智能,机器学习)