ES学习笔记之倒排索引

您所在的位置:网站首页 倒排索引算法 ES学习笔记之倒排索引

ES学习笔记之倒排索引

2024-04-14 23:15| 来源: 网络整理| 查看: 265

由于之前被面试官吊打过es的索引原理,所以本人对es的倒排索引进行一个学习和总结。 学习小册子:

Elasticsearch 从入门到实践 - spoofer - 掘金小册 (juejin.cn)

涉及到的数据结构和算法: 倒排索引 FST(Finite State Transducers) 跳表 bitmap 二分法查找 ... 什么是倒排索引(Inverted Index)

索引从本质来讲就是一种为了加快检索数据的存储结构,就像书的目录一样,可以很快地帮助我们查找到某个章节所在的位置。 常见的索引有哈希表、B+树、有序数组等等,像这种实体 ID 到数据实体内容的关联关系的索引我们称为正排索引,正排索引非常适合处理键值查询的场景。 与正排索引不同,倒排索引是把保存词项到实体ID关系的索引,倒排索引设计中使用到了很多数据结构和算法,使查询效率更高,同时也能够处理大批量的数据。

倒排索引的组成

如果有以下几个短语:

倒排索引学习笔记 今天我要学习 好好珍惜今天的日子 词项文档数量文档id倒排11索引11学习21,2笔记11今天22,3我要12好好13珍惜13的13日子13

如果我们要找包含学习的短语,没有索引的话,那么我们需要对文档进行遍历才能找到对应的文档id,为了提高效率需要为所有数据建立索引,比如倒排索引。 虽然索引会对我们的数据进行排序,使我们筛选查询的时候定位到数据,一旦数据量大的时候,我们遍历的数据就很庞大,索引占用空间也很庞大,查询效率不高,就会面临以下几种问题:

分词形成的词项(term)可能是海量的,需要可以在内存和磁盘上高效存储; 既然词项是海量的,那么如何快速找到对应的词项也是个问题; 每个词项对应的文档数可能非常多,也就是上图中文档列表的链表很长; 在词项对应的文档多的情况下,多个文档列表间做交集的效率将是个挑战。

倒排索引为了解决以上几个问题,使用词项索引(Term Index)来解决上述 1 和 2 的问题,而对于 3 和 4,Lucene 对数据进行了压缩处理,使用 Roaring Bitmaps、跳表等技术来进行快速求交集。 倒排索引的组成主要有3部分, Term Index、Term Dictionary、Posting List 如下图:

Es组成部分.drawio.png

其中,Term Dictionary 保存的是词项,随着词项越来越多,从 Term Dictionary 中查找一个词项势必越来越慢,所以必须对这些词项做索引,从而有了 Term Index,它是 Term Dictionary 的索引,最好设计得越小越好,这样缓存在内存中也没有压力。Posting List 保存着每个词项对应的文档 ID 列表(其实还有其他信息,这里为了方便理解,只显示 ID)。

Term Index

Term Index作为Term Dictionary的索引,需要尽量确保资源消耗小,使之可以缓存在内存中,并且还要确保查询数据有较低的复杂度。 如下图所示,Term Index 只使用公共前缀做索引,那本身要存储 coach、cottage 两个字符串的索引,现在只需要存储 co 一个就行了。这样的话,拥有同一公共前缀的 Term 越多,实际上就越省空间,并且这种设计在查找的时候复杂度是公共前缀的长度:O(len(prefix)) 。对于前缀索引的实现,业界使用了 FST 算法来解决。FST(Finite State Transducers)是一种 FSM(Finite State Machines,有限状态机),并且有着类似于 Trie 树的结构,可以直接根据前缀就找到对应的term在词典中的位置。使用 FST有以下好处:

通过对 Term Dictionary 数据的前缀复用,压缩了存储空间; 高效的查询性能,O(len(prefix))的复杂度; 构建后不可变。(事实上,倒排索引一旦生成就不可变了。)

事实上,FST算法很复杂,有时间我会再研究!!!

Es组成部分-第 2 页.drawio.png

Term Dictionary

Term Dictionary 保存着 Term 与 Posting List 的关系,存储了 Term 相关的信息,如记录了包含该 Term 的文档数量(DocFreq)、Term 在整个 Segment 中出现的频率等,还保存了指向 Posting List 文件的指针(文档 ID 列表的位置、词频位置等)。Term Dictionary为所有Term做好排序,并且进行分块保存,并且只保存Term的后缀。

Posting List

Posting List不仅保存了文档的Id,还有词频、位置等等,Lucene 把这些数据分成 3 个文件进行存储:

.doc 文件,记录了文档 ID 信息和 Term 的词频,还额外记录了跳跃表的信息,用来加速文档 ID 的查询;并且还记录了 Term 在 pos 和 pay 文件中的位置,有助于进行快速读取。 .pay 文件,记录了 Payload 信息和 Term 在 doc 中的偏移信息; .pos文件,记录了 Term 在 doc 中的位置信息。

Posting List 主要面临着两个问题:

如何节省存储? 如何快速做交集? 1. 如何对数据进行压缩?

核心的思想都是:用最少的位数表示原数据,并且兼顾数据读取效率

PackedBlock VIntBlock 使用文档 ID 差值存储来节省空间

以上的方式的过程中,就是文档 ID 使用增量编码,数据分块存储、数据按需分配存储空间,而这整个过程叫做 FOR(Frame Of Reference)

2. 如何快速对数据求交集? 位图 使用缺点就是空间消耗大 Roaring Bitmaps 使用跳表加速多个列表交集的求解 总结和思考

ES为了提高查询速率和节省空间,做了很多工作。 Es倒排索引组成包含:Term Index,Term Dictonary,Posting List.

Term Index 是 Term Dictionary 的索引,使用它可以快速判断一个 Term 是否存在,并且可以找到这个 Term 在 Term Dictionary 存储的块地址。Term Index 使用了 FST 来实现,其有着小巧且复杂度低的特点。 而 Term Dictionary 是存储 Term 信息的地方,其内容包括 Term、包含该 Term 的文档的数量、Term 在整个 Segment 中出现的频率等。 在 Posting List 的实现中,Lucene 使用 PackedBlock 和 VIntBlock 对整数进行压缩的思路,使用 Roaring Bitmaps 和跳表来解决列表求交集的方案,保证高频filter查询速度的同时降低存储空间消耗。


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3