Elasticsearch核心技术与实战学习笔记 第三章12 倒排索引介绍

一 序

  本文属于极客时间Elasticsearch核心技术与实战学习笔记系列。

 本节纯讲理论的,如果了解过倒排索引的可以跳过。

二 相关阅读

先说下我自己的理解,不一定准确。错误之处欢迎指正。

  一说到索引肯定会想起MySQL的索引。就是有关索引的目的:为了快速查找到你要的数据。

MySQL的B+索引,是为了读优化的。有序性等特征适合的业务场景不是复杂查询。

我们可以想下,涉及到倒排索引的场景就是根据单词去找文档的,这个量很大,不能吧所有索引数据都放到内存。那es怎么实现?infoq上有篇文章讲的不错。为了便于理解截取部分:原文:https://www.infoq.cn/article/database-timestamp-02/

假设有如下的数据:

这里每一行是一个document。每个document都有一个docid。那么给这些document建立的倒排索引就是:

可以看到,倒排索引是per field的,一个字段由一个自己的倒排索引。18,20这些叫做 term,而[1,3]就是posting list。Posting list就是一个int的数组,存储了所有符合某个term的文档id。那么什么是term dictionary 和 term index?

假设我们有很多个term,比如:

Carla,Sara,Elin,Ada,Patty,Kate,Selena

如果按照这样的顺序排列,找出某个特定的term一定很慢,因为term没有排序,需要全部过滤一遍才能找出特定的term。排序之后就变成了:

Ada,Carla,Elin,Kate,Patty,Sara,Selena

这样我们可以用二分查找的方式,比全遍历更快地找出目标的term。这个就是 term dictionary。有了term dictionary之后,可以用 logN 次磁盘查找得到目标。但是磁盘的随机读操作仍然是非常昂贵的(一次random access大概需要10ms的时间)。所以尽量少的读磁盘,有必要把一些数据缓存到内存里。但是整个term dictionary本身又太大了,无法完整地放到内存里。于是就有了term index。term index有点像一本字典的大的章节表。比如:

A开头的term ……………. Xxx页

C开头的term ……………. Xxx页

E开头的term ……………. Xxx页

如果所有的term都是英文字符的话,可能这个term index就真的是26个英文字符表构成的了。但是实际的情况是,term未必都是英文字符,term可以是任意的byte数组。而且26个英文字符也未必是每一个字符都有均等的term,比如x字符开头的term可能一个都没有,而s开头的term又特别多。实际的term index是一棵trie 树:

例子是一个包含 "A", "to", "tea", "ted", "ten", "i", "in", 和 "inn" 的 trie 树。这棵树不会包含所有的term,它包含的是term的一些前缀。通过term index可以快速地定位到term dictionary的某个offset,然后从这个位置再往后顺序查找。再加上一些压缩技术(搜索 Lucene Finite State Transducers) term index 的尺寸可以只有所有term的尺寸的几十分之一,使得用内存缓存整个term index变成可能。整体上来说就是这样的效果。

现在我们可以回答“为什么Elasticsearch/Lucene检索可以比mysql快了。Mysql只有term dictionary这一层,是以b-tree排序的方式存储在磁盘上的。检索一个term需要若干次的random access的磁盘操作。而Lucene在term dictionary的基础上添加了term index来加速检索,term index以树的形式缓存在内存中。从term index查到对应的term dictionary的block位置之后,再去磁盘上找term,大大减少了磁盘的random access次数。

额外值得一提的两点是:term index在内存中是以FST(finite state transducers)的形式保存的,其特点是非常节省内存。Term dictionary在磁盘上是以分block的方式保存的,一个block内部利用公共前缀压缩,比如都是Ab开头的单词就可以把Ab省去。这样term dictionary可以比b-tree更节约磁盘空间。

好了,有些这些背景知识做铺垫。你再听老师讲就清晰多了。

三 关键信息

老师讲这块的时候用了图书的目录索引做例子介绍。

  • 正排索引-文档 Id 到文档内容和单词的关联
  • 倒排索引-单词到文档 Id 的关系

倒排索引表三列:单词,次数,文档ID和位置。

  • 倒排索引包含两部分:单词词典(Team Dictionary)和倒排列表(Posting List)
  • 单词词典记录单词到倒排列表的关联关系,一般通过 B+ 树或者哈希链表实现
  • 倒排列表记录单词对应的文档结合,由倒排索引项组成
  • 倒排索引项由文档ID(docId),词频(term frequencies),单词位置(term postion),偏移量(character offsets)组成

ES 也可以指定对某些字段不做索引

  • 优点:节省存储空间
  • 缺点:字段无法被搜索

小结

要理解倒排索引与正排索引的区别,  Elasticsearch 中数据索引过程的流程:

    从文档-->分词-->term->index. 

你只能搜索在索引中出现的词条,所以索引文本和查询字符串必须标准化为相同的格式。分词和标准化的过程称为分析,下一节课讲。

猜你喜欢

转载自blog.csdn.net/bohu83/article/details/106096693