介绍
正排索引、倒排索引是搜索数据库中常见的两种索引结构。一般关系型数据库中采用正排索引,而一些文档数据库中采用倒排索引。
正排索引
- 正排索引是一种基于文档的索引结构,它将文档按照其出现的顺序进行索引,每个文档对应一个文档号,文档中的每个词条都会记录在索引中。
- 在正排索引中,可以根据文档号快速定位到对应的文档,然后再进行检索和分析。
倒排索引
- 倒排索引是一种基于词条的索引结构,它将每个词条对应的文档号列表进行索引,也就是说,对于每个词条,记录了包含该词条的文档号。
- 在倒排索引中,可以根据某个词条快速定位到包含该词条的文档列表,然后再检索和分析这些文档。
对比
- 正排索引是基于文档的索引结构,而倒排索引是基于词条的索引结构。
- 正排索引可以快速定位到文档,倒排索引可以快速定位到包含某个词条的文档列表。
- 正排索引适合于文档级别的操作,倒排索引适合于词条级别的操作。
倒排索引原理
数据结构
- 倒排索引的主要数据结构是一个包含了词条(term)和对应文档列表的数据结构。这个结构通常以哈希表(hash table)的形式存储,其中词条作为键(key),对应的文档列表则是值(value)。这样可以快速地根据词条查找到相应的文档列表。
- 对于每个词条,文档列表可以使用数组、链表、树等数据结构进行存储。常见的做法是使用压缩的数据结构来存储文档列表,以节省内存和提高检索性能。
- 为了支持快速的词项关联,通常会使用词项词典(terms dictionary)来存储词条及其对应的位置,以便在进行检索时能够快速定位到词条的位置。
示例
有以下文档:
Document 1: Hello world, this is a document.
Document 2: Hello, my name is zm
elasticSearch会将上述文档存储为:
| 词条(term dictionary) | posting list |
|---|---|
| hello | 1,2 |
| world | 1 |
| this | 1 |
| is | 1,2 |
| a | 1 |
| document | 1 |
| my | 2 |
| name | 2 |
| zm | 2 |
以上为简单的结构描述,当有数亿条数据,那么一个高频term对应的posting list可能就是数百万的,假设文档编号是int类型,1 int = 4byte,那么一百万就要4MB;而elasticSearch在各个方面都对该数据结构进行了优化。
压缩算法
当词条大面积重复时,postion list是巨大的,此时有两种压缩算法。
- frame Of reference(for):
假设目前posting list存储了文档编号为:200,300,302,350,380,403。
一共7个int类型文档编号,占用空间为7*4=28byte;for压缩算法,会对把上述更改为递增数组。变化后数组为:
而一个int类型占4byte(32bit)存储的最大数字为2147483648;此时for会压缩每个数字占用的bit。上图中最大数字为192需要9bit,最小数字2需要占用2bit,所有数字都采用9bit,一共需要7*9=63bit(8byte),同时还需要增加1bit用来记录是采用几bit进行压缩的,一共占用9byte,缩小不到原来的三分之一。但都采用同样的bit位进行压缩,当数组中有一个特别大的数字时压缩效果就打打折扣了,所以for还进一步了优化。如图:
上图中如果只采用一种bit进行压缩的话,那么最终的数据大小为 1byte + 8 * 10bit = 11byte;而采用分割数组使用2种bit进行压缩最终数据大小为 1byte + 2 * 10bit + 1byte + 6 * 6bit = 10byte (当占用不足1byte时需要进位)。
- Roaring Bitmaps(rbp):
当数据过于稀疏时,采用for压缩算法带来的压缩效果就微乎其微了。例如: 91,66000,140000,142000,280000;此时会根据65536进行取模计算,此时数据变为:
存储结构如上图;而目前container是采用的array container,由于是对65536取模,所以每一个数占16为,内存占用是线性增加的;当数据过多时会转换为bitmap container,它是一个65536个bit组成的map,总大小为8kb;相当于array container存储了4096个数。而当数据是连续的时候例如1-100w,它会直接使用runcontainer,存储结果是[1-100w],只需要8byte,压缩到了极致。
FST构建过程
词项字典(term dictionary)和词项索引采用的fst压缩算法;fst的结构如下:
对开头和结尾都有进行复用;es具体构建fst是一个很复杂的过程,后续在写一篇文章补充。上图网址:examples.mikemccandless.com/fst.py?term…
提问
以上压缩算法默认document id为int类型,如果是其他类型如何处理? document id采用自增,消耗殆尽了es如何处理?
原创:转载请附链接