论文笔记 - The Case For Learned Index Structures

这篇 paper 的笔记实在是 delay 了好久= =,然而也没有读太细致,就大致浏览了几遍~

paper 地址 ⬇️

The Case For Learned Index Structures

Introduction

当我们需要查询数据库中的某条数据时,这数据在数据库中的 index 就是我们想要的答案,数据库对我们的重要性不言而喻。

现有的索引结构中,B+ 树对于范围查询无疑是最佳的,哈希表对于 kv 查询是最合适的,而布隆过滤器更多用于查询 key 是否存在于某个数据集中,但是这些索引结构的优化大多是基于数据最差的情况,并且读写相对均匀进行优化,这里作者举了一个极端的例子来说明,比如我们的数据集就是1-100M,那么这时候如果使用 B+ 树其实不是最合理的,因为 key 值本身就可以作为偏移量使用,如果使用 B+ 树的话,无疑是把 O(1) 的时间复杂度变成了 O(logn),并且由于索引的存在,所以内存空间也会由 O(1) 变成 O(n)。换句话说,当我们了解数据分布的情况下,其实可以优化数据库的索引。

基于这个想法,在这篇 paper 中,作者认为索引结构也可以视作模型,因为它们同样“预测”了给定 key 的 position,同时探索了数据库索引 key → value 这个过程中的 B+ 树和布隆过滤器这些传统索引结构在多大程度上可以被训练好的网络模型代替。

这篇 paper 主要讨论的是只读类型,但是同样也在 paper 内讨论了如何扩展到写多读少的数据库场景中,至于数据库中的一些其他操作,比如 join 等,将会是未来的一个工作方向,不在这篇 paper 的讨论范围。

Range Index

对于区间查询而言,作者认为它本身就是一个模型,给定一个 key 值的时候去预测 key index 的 position,B+ 树可以被回归树代替,而 B+ 树中的 pagesize 相当于 ML 模型中的 最大最小误差。但是我们想要用 ML 模型代替 B+ 树的时候还有一些挑战,

  1. 当 B+ 树在内存中进行插入或者查找操作的时候开销是很小的
  2. B+ 树可以将 key 映射到不连续的磁盘或者内存的 page 上
  3. 如果模型不是单调递增时,当 key 不存在于 set 中,模型可能会返回一个不在最大最小误差范围内的 position

但是针对区间查找,使用模型代替 B+ 树依然会有很多的好处,这里作者举了一个和 introduction 中相似的例子来说明,使用 ML 模型代替 B+ 树的时候,查找操作的复杂度会从 O(logn) 变成常数复杂度。所以这里关键的挑战就在于如何根据模型的精度平衡模型的复杂度。

Range Index 模型抽象为 CDF

将 index 视作模型的时候,key 作为输入,对应 key 的记录的 position 作为预测结果,对于点查询,记录的顺序是无所谓的,但是对于区间查询而言,数据必须是有序的,这样才能有效的查到对应的记录。这样的话我们就观察到一个非常有趣的现象,预测给定有序的数组内 key 的 position 近似累计分布函数(CDF),我们可以建模数据的 CDF 来预测数据的 position,

p = F(Key)*N

其中,p 是位置的估计,F(Key) 是估计的 CDF,用来估计一个 x ≤ key 的概率,即P(x≤Key),N 是 key 的个数。观察新的数据集会有一些有趣的发现,

  1. B 树通过构建一颗回归树来学习数据分布,线性回归模型可以通过最小化线性方程的方差来学习数据分布
  2. 学习 CDF 分布我们可以受益于过去多年的研究
  3. 学习 CDF 对于优化其他类型的索引结构和算法起着关键作用,会在这篇 paper 的后面讲到

接着作者尝试使用 200 M 的 web 服务日志记录中的时间戳作为数据集来训练模型,2层宽度为32的全连接的神经网络使用 ReLU 作为激活函数,时间戳作为输入,position 作为 label,使用 TensorFlow 和 Python 进行模型训练,大约需要花费 80000 纳秒进行模型的训练,查询几乎不花费时间,作为对比,B 树查找同样的数据大约只需要 300 纳秒,相差两个数量级,整个 key 空间查找大约快2-3倍,可能是由以下原因导致的,

  1. TensorFlow 更适用于大的模型,尤其是使用 Python 作为前端
  2. 最后一公里的精度问题,虽然整体数据分布看上去接近于 CDF,很平滑,但是放大某个点的数据分布的时候,我们会发现数据分布很不规则,所以如何解决最后一公里的精度问题就十分重要
  3. 经典的机器学习问题,最终的目标是想要减小平均误差,但是我们查找索引,是希望获得最佳预测,最终是期望找到 key 的真实的 position
  4. B+ 树十分高效,因为顶层的节点也就是索引都在缓存中,但是其他模型无法利用缓存的高效性,比如如果我们使用神经网络,那么需要使用所有的权重来预测最终的结果,权重如果在内存中的话开销就会比较大

The RM Index

为了解决 ML 模型替代 B+ 树的最后一公里精度问题,paper 中提出了 LIF 和递归模型索引,主要使用简单的全连接神经网络。

The Learning Index Framework

LIF 可以看做一个索引综合系统,给定一个索引规范,LIF 可以生成不同的索引配置,优化并且自动测试,可以即时的学习简单的模型,也可以依赖 TensorFlow 获取复杂的模型,但是不使用 TensorFlow 进行预测,并且当给定一个使用 TensorFlow 训练好的模型 LIF 可以自动提取权重,并根据规范生成搞笑的索引结构。使用 XLA 的 TensorFlow 可以支持代码编译,但是主要用于大型模型,相比之下 LIF 专注于小型模型,所以必须减少用于管理大型模型的许多不必要的开销,引用21中的已经展示了如何消除 Spark 运行时间不必要的开销,目前 LIF 计算简单的模型可以仅在 30 纳秒内完成。

这一部分内容主要用于解决当数据分布改变时需要重新训练模型的时间开销。

The Recursive Model Index

为了解决最后一公里精度的问题,paper 中提出了递归回归模型。使用单个模型将误差从100M 减少到百数量级是很困难的,但是从100M 将误差减小到10k 是很容易的,使用模型代替 B 树的前两层,带来的精度增益就是100*100=10000,同样,将误差从1000减小到100也很容易,因为模型只需要关注数据的一个子集即可。

因此,paper 提出了递归回归模型,如图,

image

每一层中 key 作为输入,并基于此挑选出另一个模型,直到最后一层预测最终的索引位置。

这种模型结构的好处是,

  1. 很容易学习整体数据分布
  2. 将整个空间分割为更小的子区间,每个子区间都类似于一个 B 树或者决策树,更容易去解决最后一公里的精度问题
  3. 不同的层之间不需要搜索,比如 model 1.1 输出的 y 是一个偏移量,可以直接用于挑选下一层的模型

递归模型索引的另一个优点是能够使用混合模型,比如顶层,可能使用 ReLU 的神经网络是最好的,因为可以学习大范围的复杂数据分布,但是下层模型可能使用简单的线性回归模型就可以了,因为时间和空间的开销都相对更小一些,同时,如果数据分布很难学习,我们甚至可以设置阈值,在最终阶段使用传统 B 树。

image

4-10行实现了基于顶点模型进行训练,并将范围内的 key 存入;11-14行,根据阈值决定是否使用 B 树代替模型。

搜索策略

paper 中提出了三种搜索策略,

  1. 模型二分搜索:默认搜索策略,类似传统二分搜索,不同点在于初始的中间点被设置为模型预测的结果
  2. Biased Search:基于二分搜索进行修改,新的中间点基于最后一层模型的标准偏差σ设置,比如,当 key 比中间节点大的时候,middle = min(middle+σ, (middle+right)/2)
  3. Biased Quaternary Search:同时查找三个点,pos-σ,pos,pos+σ,需要 CPU 可以从主存中并行获取多个数据地址

结论

使用的数据集

  1. Web log
  2. Map
  3. 合成数据集

使用模型训练比 B 树整体上而言,不论是查询时间还是存储空间都有了不止一个数量级的降低,但是适用的数据集比较有限,比如使用 web log 的时间戳的数据集进行训练的时候,由于时间戳的分布不规则,所以基本上是上面说到的大部分依赖于 B 树的 bad case,搜索策略对于 web log 比较有效果,但是对于其他数据集而言,搜索策略的影响不大。

Point Index

对于点查询,是将 Hash Function 替换为 Model,这里的核心不在于存储,而在于减少哈希碰撞,并且减少 key 的存储空间。使用 model 替换 hash function,学习的内容和 key 和 value 本身没有关系,只是学习了 CDF 分布,因为点查询是不能保证 key 单调递增的,如果不能保证单调递增,那么 key 的分布本身也不符合 CDF 分布,当学习 CDF 足够好的时候,就会保证区分度,这样再使用 key 的大小 M 来将这个 hash 的值扩展开,这样就可以保证没有碰撞。

但是如果真的出现碰撞的话,处理方法和 hash function 一样,使用链表来处理。

h(K) = F(K) * M

结论

hash function 使用 model 进行替换后,查询时间没有缩短,但是 key 空间确实有效的减少了,提高了空间利用率。

Existence Index

对于判断某个 key 是否存在于数据集内,目前的场景是使用布隆过滤器,但是布隆过滤器有一定的误判率,如果要提升精度减少误判率就势必要增加 bitmap。对于 hash function 来说,我们期望的 f(x) 使得不同的 key 冲突越少越好,但是对于布隆过滤器来说,我们期望存在的 key 和不存在的 key 它们在自己的 f(x) 内冲突越多越好,这样可以用更小的 bitmap 表示更多的 key,我们想要使用 ML model 代替布隆过滤器时,我们期望提供特定的假阳性,并且假阴性为0。paper 中介绍了两种学习布隆过滤器的方法,

将布隆过滤器视作一个分类问题

D = {(xi, yi= 1)|xi∈ K} ∪ {(xi, yi= 0)|xi∈ U}

我们需要训练这样一个神经网络,使得 log 损失函数最小。为了满足假阴性为0这个条件,我们创建一个溢出的布隆过滤器,根据阈值学习一个模型,当输出结果大于等于阈值的时候,我们认为这个 key 是存在于 set 中的,当小于阈值时,则去 check 溢出的布隆过滤器。

简单的说,就是将存在的 key 和不存在的 key 划分为两个数据集,然后融合到一个集合中进行训练,最小化一个 log 损失函数。

image

使用 model hashes 学习布隆过滤器

将布隆过滤器视作一个分类问题时与布隆过滤器中的散列函数本身是矛盾的,因为没有区间具有非零的 FNR,我们可以使用 f(x) 映射到 m 的位数组上,f(x) 映射范围是[0,1],所以我们可以假设 d 如下,作用是离散化空间,

image

所以我们可以使用 d(f(x)) 作为散列函数,这样可以将存在的 key 映射到 bit 的高位上,将不存在的 key 映射到 bit 的低位上。

f(x) ∈ [0,1],当 key 不存在时,f(x)更接近于0,反之,更接近于1,所以 key 大多分布在高位上,non-key 大多分布在低位上。

结论

空间利用率确实有所提升,并且模型精度越高,占用内存越少,但没有对比数据作为支撑。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,463评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,868评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,213评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,666评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,759评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,725评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,716评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,484评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,928评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,233评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,393评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,073评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,718评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,308评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,538评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,338评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,260评论 2 352