Elasticsearch倒排索引

文本字段存储在倒排索引中、数字字段和地理字段存储在BKD树(Bkd树是一种动态索引数据结构,能高效且可伸缩地索引大的多维点数据集。它有 (1) 极高的空间利用率和 (2) 优秀的查询、(3) 更新性能——且这三种属性在高强度更新下依旧成立。)中。由于按字段数据结构进行组合,并返回搜索结果的能力,使得Elasticsearch才能如此之快。

一、倒排索引概述

Elasticsearch 使用一种称为 倒排索引 的结构,它适用于快速的全文搜索。一个倒排索引由文档中所有不重复词的列表构成,对于其中每个词,有一个包含它的文档列表。

  • 正排索引:文档id到单词的关联关系
  • 倒排索引:单词到文档id的关联关系

例如,假设我们有两个文档,每个文档的 content 域包含如下内容:

1、The quick brown fox jumped over the lazy dog
2Quick brown foxes leap over lazy dogs in summer

为了创建倒排索引,我们首先将每个文档的 content 域拆分成单独的 词(我们称它为 词条tokens ),创建一个包含所有不重复词条的排序列表,然后列出每个词条出现在哪个文档。结果如下所示:

Term      Doc_1  Doc_2
-------------------------
Quick   |       |  X
The     |   X   |
brown   |   X   |  X
dog     |   X   |
dogs    |       |  X
fox     |   X   |
foxes   |       |  X
in      |       |  X
jumped  |   X   |
lazy    |   X   |  X
leap    |       |  X
over    |   X   |  X
quick   |   X   |
summer  |       |  X
the     |   X   |
------------------------

现在,如果我们想搜索 quick brown ,我们只需要查找包含每个词条的文档:

Term      Doc_1  Doc_2
-------------------------
brown   |   X   |  X
quick   |   X   |
------------------------
Total   |   2   |  1

两个文档都匹配,但是第一个文档比第二个匹配度更高。如果我们使用仅计算匹配词条数量的简单 相似性算法 ,那么,我们可以说,对于我们查询的相关性来讲,第一个文档比第二个文档更佳。

但是,我们目前的倒排索引有一些问题:

  • Quickquick 以独立的词条出现,然而用户可能认为它们是相同的词。
  • foxfoxes 非常相似, 就像 dogdogs ;他们有相同的词根。
  • jumpedleap, 尽管没有相同的词根,但他们的意思很相近。他们是同义词。

使用前面的索引搜索 +Quick +fox 不会得到任何匹配文档。(记住,+ 前缀表明这个词必须存在。)只有同时出现 Quick 和 fox 的文档才满足这个查询条件,但是第一个文档包含 quick fox ,第二个文档包含 Quick foxes

我们的用户可以合理的期望两个文档与查询匹配。我们可以做的更好。

如果我们将词条规范为标准模式,那么我们可以找到与用户搜索的词条不完全一致,但具有足够相关性的文档。例如:

  • Quick 可以小写化为 quick
  • foxes 可以 词干提取 --变为词根的格式-- 为 fox 。类似的, dogs 可以为提取为 dog
  • jumpedleap 是同义词,可以索引为相同的单词 jump

现在索引看上去像这样:

Term      Doc_1  Doc_2
-------------------------
brown   |   X   |  X
dog     |   X   |  X
fox     |   X   |  X
in      |       |  X
jump    |   X   |  X
lazy    |   X   |  X
over    |   X   |  X
quick   |   X   |  X
summer  |       |  X
the     |   X   |  X
------------------------

这还远远不够。我们搜索 +Quick +fox 仍然 会失败,因为在我们的索引中,已经没有 Quick 了。
但是,如果我们对搜索的字符串使用与 content 域相同的标准化规则,会变成查询 +quick +fox ,这样两个文档都会匹配!

Note:
这非常重要。你只能搜索在索引中出现的词条,
所以索引文本和查询字符串必须标准化为相同的格式。

分词和标准化的过程称为 分析 , 我们会在下个章节讨论。

二、倒排索引特点

2.1、倒排索引的结构

(1)包含这个关键词的document list
(2)包含这个关键词的所有document的数量:IDF(inverse document frequency)
(3)这个关键词在每个document中出现的次数:TF(term frequency)
(4)这个关键词在这个document中的次序
(5)每个document的长度:length norm
(6)包含这个关键词的所有document的平均长度

2.2、倒排索引不可变的好处

(1)不需要锁,提升并发能力,避免锁的问题
(2)数据不变,一直保存在os cache中,只要cache内存足够
(3)filter cache一直驻留在内存,因为数据不变
(4)可以压缩,节省cpu和io开销

2.3、倒排索引不可变的坏处

每次都要重新构建整个索引

2.4、删除与更新

段是不可变的,因此无法从旧的段中删除文档,也不能更新旧的段来反映文档的更新。相反,每个提交点 commit point 都包括一个 .del 文件,文件列出了哪个文档在哪个段中已经被删除了。

当文档被’删除’时,它实际上只是在 .del 文件中被标记为已删除。标记为已删除的文档仍然可以匹配查询,但在最终查询结果返回之前,它将从结果列表中删除。

文档更新也以类似的方式工作
当文档更新时,旧版本文档被标记为已删除,新版本文档被索引到新的段中。也许文档的两个版本都可以匹配查询,但是在查询结果返回之前旧的标记删除版本的文档会被移除。

三、倒排索引结构详解

倒排索引主要包含两部分:

  • 单词词典
  • 倒排列表

3.1、单词词典(Term Dictionary)

单词词典(Term Dictionary):是倒排索引的重要组成,记录所有文档的单词,一般都比较大,记录单词到倒排列表的关联信息。

单词词典一般用 B+Trees 来实现:
在这里插入图片描述

3.2、倒排列表(Posting List)

倒排列表(Posting List):记录了单词对应的文档集合,由倒排索引项组成。
倒排索引项主要包含以下信息:

  • 文档 ID,用来获取原始信息
  • 单词频率(TF:Term Frequency),记录该单词在该文档中的出现次数,用于后续相关性算分
  • 位置(Position),记录单词在文档中的分词位置(多个),用于做词语搜索
  • 偏移(Offset),记录单词在文档的开始位置和结束位置,用于做高亮显示

以【搜索引擎】这个关键词为例,我们来看一下倒排列表:
在这里插入图片描述

2.3、单词字段和倒排列表整合在一起的结构

在这里插入图片描述
另外,es 存储的是一个 json 格式的文档,其中包含多个字段,每个字段都会有自己的倒排索引
在这里插入图片描述

四、禁用倒排索引

对一个字段倒排索引也可以禁用,但是禁用之后不能被正常检索,示例如下:

PUT /my_index
{
  "mappings": {
    "properties": {
      "gender": {
      	 "type": "keyword",
      	 "index": false  
       }
    }
  }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值