ES查询和索引

倒排索引(Inverted Index)也叫反向索引,有反向索引必有正向索引、正排索引(doc values)。

正向索引是通过key找value,反向索引则是通过value找key。

全文搜索需要用倒排索引,而排序和聚合则需要使用正排索引。

创建索引(index)

我们在创建index的时候,也就是说创建es的表结构的时候,即通过 es http API 去创建 mappings 的时候,给每个字段(field)的属性定义里面,就设置了此字段是否可搜索、是否可聚合。

PUT /demo_index_mappings
{
    "mappings": {
        "properties": {  
            "tags": {
                "type": "text",
                "index": "true",
                "doc_values": "true" // text类型不支持
            }
        }
    }
}

倒排索引数据结构

比喻:一篇文章包含了哪些词,它从词出发,记载了这个词在哪些文档中出现过,由两部分组成:词典、倒排表

Term词典解释

Term(单词):一段文本经过分析器分析以后就会输出一串单词,这一个一个的就叫做Term(直译为:单词)

倒排索引采用 Immutable Design,一旦生成,不可更改。

不可变更的优点

1、无需考虑并发写文件的问题,避免了锁机制带来的性能问题

2、一旦读入内核的文件系统缓存,便留在那里。只要文件系统存有足够大的空间。大部分请求就会直接请求内存,不会命中磁盘,提升了很大的性能

不可变更的缺点

如果需要让一个新的文档可以被索引,需要重建整个索引。

FST的由来和设计

Term Dictionary(分词的词典) 很大,放内存不合适,也不是树形结构,没办法像B树/B+树那样部分换入内存,提高性能。

所以,Lucene单独为Term Dictionary创建了一个索引:Term Index。目的:用来记录以不同前缀开头的Term分别在Term Dictionary的起始位置。

最早设计思路

Term Index可以用HashMap来实现,当需要查找一个Term时,可以通过Hash前缀找到目标在Term Dictionary的起止点,然后二分,直到命中,得到Posting List

优化思路

从Lucene4开始,为了实现范围查询、前缀、后缀等复杂的查询语句,以及减少内存使用,Lucene采用了FST(Finite State Transducer,直译为有限状态传感器)来存储Term Index。

FST和整个ES的分词和查询的数据结构,如下

treemap

FST的优点

  1. 占用内存小,只有HashMap10分之一左右,通过对词典中单词前缀和后缀的重复利用,压缩了存储空间

  2. 查询速度快,相当于HashMap,跟Map结构很相似,有查找,有迭代

FST的缺点

结构复杂、输入要求有序、更新不易

最右边是 invert index,也可以认为是Posting List,这是倒排表。这是一个int的数组,存储了所有符合某个Term的文档id,设计要求:Posting List是有序的,好处是方便压缩

Lucene在磁盘的情况

假设我们的es数据存储路径是:/data/es

那demo的绝对路径就是:

/data/es/data/nodes/0/indices/xxxxxx/0/index/xxx.dvd 可以在最下面这个目录,查看所有文件,索引文件、源数据文件等都在这里,一个index就是一个完整的Lucene的结构。

ES的索引思路

  1. 通过多级索引的方式,减小最前端索引占用的空间。PS:与操作系统防止页表太大,分为多级页表,想法类似。

  2. 将索引放入内存,尽可能减少磁盘随机读,提高索引查找效率

  3. 在索引的各个结构Term Index、Term Dictionary、Postintg List上,采用了压缩技巧,能够减少内存占用、一次磁盘IO能读入更多的数据,从而侧面减少磁盘随机读。

唠嗑广场

野生观察家就是我,观察2022-2023年的经济情况,遇到了一定的波折,那假设经济恢复,有什么野生指标吗?我拍脑袋想,大概有这几个吧。

1、恒大、碧桂园处理结果落地,房地产变成或者回到到正常行业,GDP占比降低。

2、大学生、年轻人的就业不再困难。