Elasticsearch(一) ES中的基本概念

/ 默认分类 / 没有评论 / 165浏览

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

倒排索引


倒排索引由两个部分组成:单词词典和倒排文件。

单词词典

单词词典是由文档集合中出现过的所有单词构成的字符串集合,单词词典内每条索引项记载单词本身的一些信息以及指向“倒排列表”的指针。
单词词典是倒排索引中非常重要的组成部分,它是用来维护文档集合中所有单词的相关信息,同时用来记载某个单词对应的倒排列表在倒排文件中的位置信息。在支持搜索时,根据用户的查询词,去单词词典里查询,就能够获得相应的倒排列表。
对于一个规模很大的文档集合来说,可能包含了几十万甚至上百万的不同单词,
快速定位某个单词直接决定搜索的响应速度,所以我们需要很高效的数据结构对单词词典进行构建和查找。
常用的数据结构包含哈希加链表和树形词典结构。

倒排文件

所有单词的倒排列表顺序的存储在磁盘的某个文件里,这个文件即被称为倒排文件,倒排文件是存储倒排索引的物理文件。

索引我们都很熟悉,字典的索引,书籍的索引,比如关系型数据库中,我们经常需要设置索引来提高数据检索的效率,如下:

idname
1张三
2李四
3李二

比如我们在id列创建索引,就能快速的根据id的值检索到具体的行,每一条新的数据,id都是需要增加到索引文件中的。

什么是倒排索引?

所谓倒排索引,就是每条记录中的content会被分割成最小的数据单元,每个数据单元都会指向该条记录,和正常的索引关系正好是相反的,如下图:

keywordid
java1
redis3
mq1,2
spring3,4
python4

倒排的特点

在倒排索引中,关键字的数量并非随着文本内容的增长也线性增长。这因为不论多大数量的文本数据库,总能规范出一个关键词表搜到实际语言因素的限制,它的增长率在文本数据库达到一定规模后可以忽略不计。有人做过统计,对于1GB的文本信息来说,词汇表的大小在5MB左右。
可以试想,将一本书上所有文本均制作成关键字,并对其进行倒排,构建一个信息搜索系统。对其中的内容进行检索,在整个过程中,最消耗时间的应该倒排阶段。因为在倒排时,需要对文本进行分析,切词,还要构建索引结构,记录位置信息,同时维护内容。虽然这一阶段花时间,但是一旦完成,在搜索时将会大大节省时间。事实上,一个信息检索系统在建立索引时的速度是可以放宽的,因为这是在后台异步完成的,而其搜索速度才是影响用户最终体验的直接因素。

词频和位置

通常,仅仅知道关键字的位置是远远不够再现实场景中完成搜索的,我们还需要知道关键词出现的次数和位置

keywordid出现次数位置
java123,7
redis312
mq1,241,2,3,4
spring3,452,4,6,5,7
python431,2,3

实现时,Lucene将上面内容分别作为词典文件(TermDictionary)、频率文件(frequencies)、位置文件(positions)保存。其中词典文件不仅保存了每个关键词,还保留了指向频率文件和位置文件的指针,通过指针可以找到该关键字的频率信息和位置信息。
Lucene中使用了field的概念,用于表达信息所在位置(如标题中、文章中、URL中),在建索引中,该field信息也记录在词典文件中,每个关键词都有一个field信息,因为每个关键字一定属于一个或多个field。

索引和文档

在Elasticsearch中,文档归属于一种类型(type),而这些类型存在于索引(index)中,我们可以画一些简单的对比图来类比传统关系型数据库(只是来理解,其实不是很准确):
Relational DB -> Databases -> Tables -> Rows -> Columns
Elasticsearch -> Indices -> Types -> Documents -> Fields

Elasticsearch集群可以包含多个索引(indices)(数据库),每一个索引可以包含多个类型(types)(表),每一个类型包含多个文档(documents)(行),然后每个文档包含多个字段(Fields)(列)。 「索引」含义的区分

- Index

index是具有相似特征的文档(document)集合。例如,你可以有顾客数据的index、商品种类的index和订单数据的index。每个index都有唯一的名称(必须小写),当执行索引、搜索、更新和删除操作时都需要根据该名称找到对应的index。

- Type

type是index中的逻辑分类,在es中,在早期的版本中大家经常使用多个type,其实我们现在也还在用(用来批量移除历史数据),后来到5.X和现在的6.x中,都推荐用户一个index下面就用一个type,在后续的7.x规划中,已经计划把type从index中移除了,具体的原因,就是多个type存在很多坑。

人们经常会谈到index类似传统sql数据库的“database”,而type类似于”table”。现在想想,这是一个非常糟糕的比喻,而这个比喻会造成很多错误的假设。
在传统的sql数据库中,各个”table”之间是互相独立的,在一个表中的列都与另一个表相同名称的列无关。

1,而在我们elasticsearch中同一 Index 下,同名 Field 类型必须相同,即使不同的 Type;

2, 同一 Index 下,TypeA 的 Field 会占用 TypeB 的资源(互相消耗资源),会形成一种稀疏存储的情况。尤其是 doc value ,为什么这么说呢?doc value为了性能考虑会保留一部分的磁盘空间,这意味着 TypeB 可能不需要这个字段的 doc_value 而 TypeA 需要,那么 TypeB 就被白白占用了一部分没有半点用处的资源;

3,Score 评分机制是 index-wide 的,不同的type之间评分也会造成干扰。

4,索引元数据本身是放在主节点中维护的,同一个index中多个type,会涉及到大量字段变更及元数据变更的操作,都会导致该 Index 被堵塞或假死。我们应该对这样的 Index 做隔离,避免影响到其他 Index 正常的增删改查!

- Document

document是索引的基本单元信息。举例,你有一个客户的document、一个商品的document和一个订单的document。该document用JSON表示。
一个index/type中,可以包含任意多的document。注意,虽然document物理上存在index中,document实际上必须被分配到index中的type上。

- Field

field就是document中的每个属性了,比如客户有id,(name)姓名,(sex)性别等

最后用一张图来说明下这几个概念