一、es的基本原理与基础概念
1.1 倒排索引
源于实际应用中需要根据属性的值来查找记录。这种索引表中的每一项都包括一个属性值和具有该属性值的各记录的地址。由于不是由记录来确定属性值,而是由属性值来确定记录的位置,因而称为倒排索引(inverted
index)。带有倒排索引的文件我们称为倒排索引文件,简称倒排文件(inverted file)。
如图
1.2 索引 index
一个索引就是一个拥有几分相似特征的文档的集合。比如说,可以有一个客户 数据的索引,另一个产品目录的索引,还有一个订单数据的索引
一个索引由一个名字来标识(必须全部是小写字母的),并且当我们要对对应 于这个索引中的文档进行索引、搜索、更新和删除的时候,都要使用到这个名字
1.3 集群Cluster
一个集群就是由一个或多个服务器节点组织在一起,共同持有整个的数据,并一起提供索引和搜索功能。一个Elasticsearch集群有一个唯一的名字标识,这个名字默认就是”elasticsearch”。这个名字是重要的,因为一个节点只能通过指定某个集群的名字,来加入这个集群。
1.4 节点Node
集群中包含很多服务器,一个节点就是其中的一个服务器。作为集群的一部分,它存储数据,参与集群的索引和搜索功能
1.5 分片
分片一个索引可以存储超出单个结点硬件限制的大量数据。比如,一个具有10亿文
档的索引占据1TB的磁盘空间,而任一节点都没有这样大的磁盘空间;或者单个节点 处理搜索请求,响应太慢 为了解决这个问题,Elasticsearch提供了将索引划分成多份的能力,这些份就叫 做分片当创建一个索引的时候,可以指定你想要的分片的数量 每个分片本身也是一个功能完善并且独立的“索引”,这个“索引”可以被放置 到集群中的任何节点上 分片很重要,主要有两方面的原因
1.允许水平分割/扩展你的内容容量
2.允许在分片之上进行分布式的、并行的操作,进而提高性能/吞吐量
原则:
1.6 副本
在一个网络 /
云的环境里,失败随时都可能发生,在某个分片/节点不知怎么的就处于离线状态,或者由于任何原因消失了,这种情况下,有一个故障转移机制是非常有用并且是强烈推荐的。为此目的,Elasticsearch允许你创建分片的一份或多份拷贝,这些拷贝叫做复制分片(副本)。
副本之所以重要,有两个主要原因 1) 在分片/节点失败的情况下,提供了高可用性。
注意到复制分片从不与原/主要(original/primary)分片置于同一节点上是非 常重要的 2)
扩展搜索量/吞吐量,因为搜索可以在所有的副本上并行运行 每个索引可以被分成多个分片。一个索引有0个或者多个副本
一旦设置了副本,每个索引就有了主分片和副本分片,分片和副本的数量可以 在索引
例如:某es集群有3个节点
1.7 映射(Mapping)
mapping是处理数据的方式和规则方面做一些限制,如:某个字段的数据类型、默认值、分析器、是否被索引等等。这些都是映射里面可以设置的,其它就是处理ES里面数据的一些使用规则设置也叫做映射,按着最优规则处理数据对性能提高很大,因此才需要建立映射,并且需要思考如何建立映射才能对性能更好。
设置
创建新的索引并设置mapping信息
1.8 字段类型
es字段类型设置可选为
keyword与text的区别
keyword 映射 只能精准查询, 不能分词查询,能聚合、 排序、过滤。term是精确查找,但只支持keyword类型
text 映射 能模糊查询, 能分词查询,不能聚合、排 序
二、重要的ES理论
2.1 ES近实时特性的原理
ES的近实时性质包括以下几个方面:
当我们执行索引操作(插入、更新、删除文档)时,ES会将这些操作存储在一个缓冲区(buffer)中。这意味着虽然变更几乎立刻对用户可见,但实际上它们可能并没有立刻写入硬盘。ES会定期将缓冲区中的操作批量写入磁盘,这个操作可能会有少量延迟。
ES会定期执行一个操作叫做"刷新"。这个操作会确保在硬盘上的所有操作都被提交(committed),并且使这些变更对搜索可见。默认情况下,ES每秒执行一次刷新操作。这意味着,在某些情况下,你可能需要等待一秒钟才能搜索到最新的变更。
ES的搜索操作通常是近实时的,因为它们可以立即反映已经被索引的文档。在上述刷新操作执行前,搜索仍然可以进行,但不能保证最新的变更已经被搜索到
ES数据存储的流程图
名词解释:
也叫段,类似于倒排索引,相当于一个数据集。
提交点,记录着所有已知的段
1.数据执行流程
1、document 写入到 In-memory buffer (内存缓冲区)
2、当满足一定条件后内存缓冲区中的 documents 刷新到 高速缓存(cache)。默认1秒1次,可以通过index.refresh_interval去更改刷新时间
3、 高速缓存区(OS Cache 操作系统文件缓冲区)的数据已经可以被查询到。此时,在告诉缓存区生成新segment
4、通过fsync把缓存数据和segment刷新到磁盘。默认时间是30分钟(fsync的时间是translog的flush时间决定)。但是高速缓存区也可以搜索,所以能查
5、segment合并。合并进程选择一小部分大小相似的 segment,并且在后台将它们合并到更大的 segment 中。这并不会中断索引和搜索
2.删除和更新
segment 不可改变,所以 docment 并不能从之前的 segment 中移除或更新。所以每次 commit, 生成 commitpoint 时,会有一个 .del 文件,里面会列出被删除的 document(逻辑删除)。而查询时,获取到的结果在返回前会经过 .del 过滤。更新时,也会标记旧的 docment 被删除,写入到 .del 文件,同时会写入一个新的文件。此时查询会查询到两个版本的数据,但在返回前会被移除掉一个。
ES利用段合并的时机来真正从文件系统删除那些version较老或者是被标记为删除的文档
3.translog的作用
- document 不断写入到 In-memory buffer,此时也会追加 translog。
2.当 buffer 中的数据每秒refresh 到 cache 中时,translog 并没有进入到刷新到磁盘,是持续追加的。 - translog 每隔 5s 会 fsync到磁盘。 translog 会继续累加变得越来越大,当 translog 大到一定程度或者每隔一段时间,会执行 flush。
flush 操作会分为以下几步执行:
1.buffer 被清空。
2.记录 commit point。
3.cache 内的 segment 被 fsync 刷新到磁盘。
4.translog 被删除
2.2 路由控制
路由公式:
id是文档id,number_of_primary_shards是猪分片数
2.3 ES优化
1.每个分片占用的硬盘的容量不超过ES的最大JVM堆空间设置
2.分片数不超过节点数的3倍
3.节点数 <= 主分片 * (副本数+1)
4.设置参数延长再平衡的时间。
对于节点瞬时中断的问题,默认情况,集群会等待一分钟来查看节点是否会重新加入,
如果这个节点在此期间重新加入,重新加入的节点会保持其现有的分片数据,不会触发新的
分片分配。这样就可以减少 ES 在自动再平衡可用分片时所带来的极大开销
5.Bulk默认设置批量提交数据不能超过100M
6.减少副本的数量
ES 为了保证集群的可用性,提供了 Replicas(副本)支持,然而每个副本也会执行分
析、索引及可能的合并过程,所以 Replicas 的数量会严重影响写索引的效率。
当写索引时,需要把写入的数据都同步到副本节点,副本节点越多,写索引的效率就越
慢
7.修改内存设置
jvm.option 文件,添加如下命令来设置 ES 的堆大小,Xms 表示堆的初始大小,Xmx 表示可分配的最大内存
ES 堆内存的分配需要满足以下两个原则
①不要超过物理内存的 50%:Lucene 的设计目的是把底层 OS 里的数据缓存到内存中。如果内存太小就有大量数据需要落盘,那会降低效率
②堆内存的大小最好不要超过 32GB
最终我们都会采用 31 G 设置
-Xms 31g
-Xmx 31g
2.4 Elasticsearch 搜索的流程?
1、在初始查询阶段时,查询会广播到索引中每一个分片拷贝(主分片或者副本分片)。 每个分片在本 地执行搜索并构建一个匹配文档的大小为 from + size 的优先队列。PS:在搜索的时候是会查询 Filesystem Cache 的,但是有部分数据还在 Memory Buffer,所以搜索是近实时的。
2、 每个分片返回各自优先队列中 所有文档的 ID 和排序值 给协调节点,它合并这些值到自己的优先队 列中来产生一个全局排序后的结果列表。
1、 接下来就是取回阶段,协调节点辨别出哪些文档需要被取回并向相关的分片提交多个 GET 请求。每 个分片加载并丰富文档,如果有需要的话,接着返回文档给协调节点。一旦所有的文档都被取回了, 协调节点返回结果给客户端
说明
Query Then Fetch 的搜索类型在文档相关性打分的时候参考的是本分片的数据,这样在文档数量较少 的时候可能不够准确,DFS Query Then Fetch 增加了一个预查询的处理,询问 Term 和 document frequency,这个评分更准确,但是性能会变差
2.5 Elasticsearch的修改操作
1、通过指定文档ID和文档数据来执行索引(index)操作(这里是指修改操作)。
2、 Elasticsearch 接收到索引请求后,会将新数据存储在相同的分片上,覆盖旧数据。
3、旧数据会被标记为已删除,但不会立即从磁盘上移除,以便后续的搜索和数据恢复操作。
4、当Elasticsearch进行合并段(segment)操作时,才会清理已删除的数据
2.6 Elasticsearch新增一个字段
1、确定新字段的数据类型。
2、使用 PUT 或 POST 请求更新索引映射
三、使用kibana操作es的常见命令
3.1 基础命令
#所有节点
#查看主节点
#查看健康状况
#查看所有索引
#查看所有索引及数据量
#查看索引数据
结果说明:
#查看分词器装没有
#最大分词
#最小分词
#所有节点
dilmrt代表全部权限
添加索引
删除索引
查看索引
3.2 索引数据的操作
3.2.1 建立索引并插入数据
3.22 索引数据的增删改查
1、当前索引 doc类型的所有文档
GET /索引名称/类型/_search
GET /eslog/_search
SQL: select * from eslog
#2、条件查询, 如要查询age等于28岁的 _search?q=:**
GET /索引名称/类型/_search?q=:**
GET /es_db/_search?q=age:28
SQL: select * from student where age = 28
3、范围查询, 如要查询age在25至26岁之间的 _search?q=[ TO ] 注 意: TO 必须为大写
GET /索引名称/类型/_search?q=***[25 TO 26]
GET /es_db/_search?q=age[25 TO 26]
SQL: select * from student where age between 25 and 26
4、根据多个ID进行批量查询 _mget ,注意:这里的id是指es的生成的id(若未指定)不是数据里的id
GET /索引名称/类型/_mget
GET /es_db/_mget { “ids”:[“1”,“2”] }
SQL: select * from student where id in (1,2)
5、查询年龄小于等于28岁的 :<= (同理:>,<,>=,<=)
GET /索引名称/类型/_search?q=age:<=**
GET /es_db/_search?q=age:<=28
SQL: select * from student where age <= 28
6、分页查询 from=&size= (注意:from+size不能超过10000(默认值,可以手动修改))
GET /索引名称/类型/_search?q=age[25 TO 26]&from=0&size=1
GET/es_db/_search?q=age[25 TO 26]&from=0&size=1
SQL: select * from student where age between 25 and 26 limit 0, 1
7、对查询结果只输出某些字段 _source=字段,字段
GET /索引名称/类型/_search?_source=字段,字段
GET /es_db/_search?_source=name,age
SQL: select name,age from student
8、对查询结果排序 sort=字段:desc/asc
GET /索引名称/类型/_search?sort=字段 desc
SQL: select * from student order by age desc
3.23 DSL语言高级查询
1、 根据名称精确查询姓名 term, term查询不会对字段进行分词查询,会 采用精确匹配 注意: 采用term精确查询, 查询字段映射类型属于为keyword
1.1 多关键字精确查询
2、 根据备注信息模糊查询 match, match会根据该字段的分词器,进行分 词查询,多个词条之间是or的关系
3、 多字段模糊匹配查询与精准查询 multi_match
注:json请求字符串中部分字段的含义
range:范围关键字
gte 大于等于
lte 小于等于
gt 大于
lt 小于
now 当前时间
- 范围查询
5.分页、输出字段、排序综合查询
- 过滤器方式查询,它的查询不会计算相关性分值,也不会对结果 进行排序, 因此效率会高一点,查询的结果可以被缓存。
- 按条件删除
8.复杂删除里面的条件跟查询条件一样的,例如按时间范围删除
将 book 字段设置为 keyword 映射 (只能精准查询, 不能分词查询,能聚合、 排序、过滤)将 book 字段设置为 text 映射 (能模糊查询, 能分词查询,不能聚合、排 序)。
#查看es索引字段的类型(keyword或者text)
9.过滤返回字段
:来指定想要显示的字段
:来指定不想要显示的字段
10 .组合查询 把各种其它查询通过(必须 )、(必须不)、(应该)的方式进行组合
11.模糊查询
返回包含与搜索字词相似的字词的文档。
编辑距离是将一个术语转换为另一个术语所需的一个字符更改的次数。这些更改可以包括:
更改字符(box → fox)
删除字符(black → lack)
插入字符(sic → sick)
转置两个相邻字符(act → cat)
fuzzy 查询会用到两个很重要的参数,
:表示输入的关键字通过几次操作可以转变成为ES库里面的对应field的字段
操作是指:新增一个字符,删除一个字符,修改一个字符,每次操作可以记做编辑距离为1,如中文集团到中威集团编辑距离就是1,只需要修改一个字符;该参数默认值为0,即不开启模糊查询,同样,如果fuzziness值在这里设置成2,会把编辑距离为2的东东集团也抓出来。
:表示限制输入关键字和ES对应查询field的内容开头的第n个字符必须完全匹配,不允许错别字匹配。如这里等于1,则表示开头的中字必须匹配,不匹配则不返回,默认值也是0。加大prefix_length的值可以提高效率和准确率。
12.排序
sort 可以让我们按照不同的字段进行排序,并且通过order指定排序的方式。desc降序,asc升序。
13.高亮查询
在使用match查询的同时,加上一个highlight属性:
pre_tags:前置标签
post_tags:后置标签
fields:需要高亮的字段
title:这里声明title字段需要高亮,后面可以为这个字段设
fragment_size :指定高亮数据展示多少个字符回来
14 短语查询
对要查询的句子短语作为整体去模糊查询,采用短语查询才得行(matchPhraseQuery)
15 字段超长的数据
比如吧我要查询索引中的某些字段的长度大于20的全部数据,在数据清洗时常常要求删除字段长度大于多少的数据。怎么整?
16 设置它的默认值的值
注意:es使用from +size处理分页问题时,会将所有数据全部取出来,然后再截取指定范围的数据返回,所以当数据量较大时,这种机制会存在内存溢出的可能,所以使用。
17 es聚合分组,组数过多解决办法
问题: trying to create too many buckets.must be less than or equal to :[20000] but was [86391].this limit can be set
by changing the [search.max_buckets] clusterlevel setting.
原因:es7版本之后默认支持最大分桶为65535,如果大于这个值,则不会查询到数据,所以可以将这个值设置更大
18 根据es的_id查询
四、ES的调优
默认情况下 ES 每秒生成一个 segment 文件,当达到一定阈值的时候 会执行merge,merge 过程发生在 JVM中,频繁的生成
Segmen 文件可能会导致频繁的触发 FGC,导致 OOM。为了避免避免这种情况,通常采取的手段是降低 segment
文件的生成频率,手段有两个,一个是 增加时间阈值,另一个是增大 Buffer的空间阈值,因为缓冲区写满也会生成 Segment 文件
增加 flush 时间间隔
增加refresh_interval的参数值
增加Buffer大小
关闭副本
使用多个工作线程
segment段调优
index.number_of_shards:控制数据的分布和搜索的并行度,增加分片数会增加资源消耗,但可以提高系统的容错性和并行化能力。
index.number_of_replicas:控制数据的冗余副本数,增加副本数会增加资源消耗,但可以提高系统的容错性。
index.refresh_interval:控制段的刷新频率。默认情况下,每隔1秒,内存中的文档会被刷新到一个新的段。可以根据数据的实时性需求进行调整。
index.translog.flush_threshold_size:控制事务日志刷新的阈值大小。
cluster.routing.allocation.disk.watermark:控制数据分配对磁盘空间的敏感度。