ES 优化概述|学习笔记

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: 快速学习 ES 优化概述。

开发者学堂课程【ElasticSearch 最新快速入门教程ES 优化概述】学习笔记,与课程紧密联系,让用户快速学习知识。

课程地址:https://developer.aliyun.com/learning/course/642/detail/10682


ES 优化概述

 

内容介绍:

一、硬件环境的选择

二、系统拓扑设计

三、ES 的内存设置

四、集群分片设置

五、Mapping 建模

六、索引优化设置

七、查询优化

八、集群运营与恢复

 

Elasticsearch 是目前大数据领域最热门的的技术栈之一,经过近8年的发展,已从0.0.X版升级至7.X版本,增加了很多特性和功能,但是在主体架构上,还是没有太多的变化。

 

一、硬件环境的选择

如果有可能,尽可能 SSD 硬盘以及较为强悍的 CPU。ES 的厉害之处在于 ES 本身的分布式架构以及 lucene 的特性。值函数的输出,IO 的提升,会极大改进 ES 的速度和性能。

 

二、系统拓朴设计

ES 集群在架构拓扑时,一般都会采用 Hot-Warm 的架构模式,即设置3种不同类型的节点:Master 节点、Hot 节点和 Warm 节点。

1. Master 节点设置

一般会设置3个专用的 master 节点,以提供最好的弹性当然,必须注意 discovery.zen.minimum_master nodes 属性的设置,以防 split-brain 问题,使用公式设置:

N/2+1(N为候选 master 节点数)。该节点保持:node.data:false;因为 master 节点不参与查询、索引操作,仅负责对于集群管理所以在 CPU、内存、磁盘配置上,都可以比数据节点低很多。

2. Hot 节点设置

又称索引节点(写节点),专用于数据储存的节点,同时近期频繁使用的索引都会保存在 Hot 节点中。属于 IO 和 CPU密集型操作,建议使用SSD固态硬盘的磁盘类型,保持良好的写性能;节点的数量设置一般是大于等于3个。将节点设置为 hot 类型:node.attr.box_type: hot。针对 index,通过设置

index.routing.allocation.require.box_

type:hot 可以设置将索引写入 hot 节点。

3. Warm 节点设置

用于不经常访问的 read-only 索引。由于不经常访问,一般使用普通的磁盘即可。内存、CPU 的配置跟 Hot 节点保持一致即可;节点数量一般也是大于等于3个。

当索引不再被频繁查询时,可通过

index.routing.allocation.require.box_type:warm,将索引标记为 warm,从而保证索引不写入 hot 节点,以便将 SSD 磁盘资源用在刀刃上。一旦设置这个属性,ES 会自动将索引合并到 warm 节点。同时,也可以在elasticsearch.yml 中设置 index.codec:best compression 保证 warm 节点的压缩配置。

4. Coordinating 节点

协调节点用于做分布式里的协调,将各分片或节点返回的数据整合后返回。

在ES集群中,所有的节点都有可能是协调节点,但是,可以通过设置 node.master、nodedata、node.ingest 都为false 来设置专门的协调节点,需要较好的 CPU 和较高的内存。

 

三、ES 的内存设置

由于 ES 构建基于 lucene,而 lucene 设计强大之处在于 lucene 能够很好的利用操作系统内存来缓存索引数据,以提供快速的查询性能。lucene 的索引文件 segements 是存储在单文件中的,并且不可变,对于 OS 来说,能够很友好地将索引文件保持在 cache 中,以便快速访问;因此,我们很有必要将一半的物理内存留给 lucene;另一半的物理内存留给 ES(JVM heap)。

所以,在 ES 内存设置方面,可以遵循以下原则:

1. 当机器内存小于64G 时,遵循通用的原则,50%给 ES,50%留给 lucene。

2.当机器内存大于64G 时,遵循以下原则:

(1)如果主要的使用场景是全文检索,那么建议给 ESHeap 分配4~32G 的内存即可;其它内存留给操作系统,供1ucene 使用(segments cache),以提供更快的查询性能。

(2)如果主要的使用场景是聚合或排序,并且大多数是 numerics,dates,geo_points 以及 not_analyzed的字符类型,建议分配给 ES Heap 分配4~32G 的内存即可,其它内存留给操作系统,供1ucene 使用(doc values cache),提供快速的基于文档的聚类、排序性能。

(3)如果使用场景是聚合或排序,并且都是基于 analyzed 字符数据,这时需要更多的 heap size,建议机器上运行多 ES 实例,每个实例保持不超过50%的 ESheap 设置(但不超过32G,堆内存设置32G以下时,JVM 使用对象指标压缩技巧节省空间),50%以上留给lucene。

3.禁止 swap,一旦允许内存与磁盘的交换,会引起致命的性能问题。通过:在 elasticsearch.yml 中 bootstrap.memory_lock:true,以保持 JVM 锁定内存,保证 ES 的性能,实现内存与磁盘的交互。

4.GC 设置原则:

(1)保持 GC 的现有设置,默认设置为:Concurrent-Mark and Sweep(CMS),别换成 G1GC,因为目前 G1还有很多 BUG。

(2)保持线程池的现有设置,目前 ES 的线程池较1.x 有了较多优化设置,保持现状即可;默认线程池大小等于 CPU 核心数。

如果一定要改,按公式((CPU 核心数*3)/2)+1设置;不能超过 CPU 核心数的2倍;但是不建议修改默认配置,否则会对CPU 造成硬伤。

 

四、集群分片设置

ES 一旦创建好索引后,就无法调整分片的设置,而在 ES 中,一个分片实际上对应一个 lucene 索引,而 lucene 索引的读写会占用很多的系统资源,因此,分片数不能设置过大;所以,在创建索引时,合理配置分片数是非常重要的。

一般来说,我们遵循一些原则:

1. 控制每个分片占用的硬盘容量不超过 ES 的最大 JVM 的堆空间设置(一般设置不超过32G,参加上文的 JVM 设置原则),因此,如果索引的总容量在500G 左右,那分片大小在16个左右即可;当然,最好同时考虑原则2。

2.考虑一下 node 数量,一般一个节点有时候就是一台物理机,如果分片数过多,大大超过了节点数,很可能会导致一个节点上存在多个分片,一旦该节点故障,即使保持了1个以上的副本,同样有可能会导致数据丢失,集群无法恢复。所以,一般都设置分片数不超过节点数的3倍。


五、 Mapping 建模

1.尽量避免使用 nested(嵌套)或 parent/child(父子关系),能不用就不用;nested query 慢,parent/child query 更慢,比 nested query 慢上百倍;因此能在 mapping 设计阶段搞定的(大宽表设计或采用比较 smart 的数据结构),就不要用父子关系的 mapping。

2.如果一定要使用 nestedfields,保证 nestedfields 字段不能过多,目前 ES 默认限制是50。参考: index.mapping.nested_fields.lim

it :50。因为针对1个 document,每一个 nestedfield,都会生成一个独立的 document,这将使 Doc 数量剧增,影响查询效率,尤其是 JOIN 的效率。

3. 避免使用动态值作字段(key),动态递增的 mapping,会导致集群崩溃;同样,也需要控制字段的数量,业务中不使用的字段,就不要索引。控制索引的字段数量、mapping 深度、索引字段的类型,对于 ES 的性能优化是重中之重。以下是 ES 关于字段数、mapping 深度的一些默认设置:

index.mapping nested_objects.limit:10000 index.mapping.total_fields.limit:1000 index.mapping.depth.limit: 20

 

六、索引优化设置

1.设置 refresh_interval 为-1,同时设置 number_of_replicas 为0,通过关闭 refresh 间隔周期,同时不设置副本来提高写性能。

2.修改 index_buffer_size 的设置,可以设置成百分数,也可设置成具体的大小,大小可根据集群的规模做不同的设置测试.

indices.memory.index_buffer size:10%(默认)

indices.memory.min_index_buffer_size: 48mb(默认) indices.memory.max_index_buffer_size

3.修改 translog 相关的设置:

(1)控制数据从内存到硬盘的操作频率,以减少硬盘I0。可将 sync_interval 的时间设置大一些 index.translog.sync_interval: 5s(默认)

(2)控制 tranlog 数据块的大小,达到 threshold 大小时,才会 flush 到 lucene 索引文件。

index.translog.flush_threshold_size:512mb(默认)

4. id 字段的使用,应尽可能避免自定义 d,以避免针对 ID 的版本管理;建议使用 ES 的默认!D 生成策略或使用数字类型ID 做为主键。

5. all 字段及 source 字段的使用,应该注意场景和需要,all 字段包含了所有的索引字段,方便做全文检索,如果无此需求,可以禁用;source 存储了原始的 document 内容,如果没有获取原始文档数据的需求,可通过设置 includes、excludes 属性来定义放入 source 的字段。

6.合理的配置使用 index 属性,analyzed 和 not analyzed,根据业务需求来控制字段是否分词或不分词。只有groupby 需求的字段,配置时就设置成 not_analyzed,以提高查询或聚类的效率。

 

七、查询优化

1.query_string 或 multi_match的查询字段越多,查询越慢。可以在 mapping 阶段,利用 copy_to 属性将多字段的值索引到一个新字段,multi_match 时,用新的字段查询。

2.日期字段的查询,尤其是用 now 的查询实际上是不存在缓存的,因此,可以从业务的角度来考虑是否一定要用now,毕竟利用 query

cache 是能够大大提高查询效率的。

3.查询结果集的大小不能随意设置成大得离谱的值,如 query.setSi

ze 不能设置成 Integer.MAX_VALUE,因为 ES 内部需要建立一个数据结构来放指定大小的结果集数据。若设置的值过大,可能会导致内存崩溃。

6. 尽量避免使用 script(脚本),万不得已需要使用的话,选择 painl

ess&experssions 引擎。一旦使用 script 查询,一定要注意控制返回,千万不要有死循环(如下错误的例子),因为 ES没有脚本运行的超时控制,只要当前的脚本没执行完,该查询会一直阻塞。

如:

{

"script_fields" : {

"test1" : {

"lang”:“groovy”,

"script":"while(true){print 'don't use script'}"

}

}

}

5. 避免层级过深的聚合查询,层级过深的 groupby,会导致内存、CPU 消耗,建议在服务层通过程序来组装业务,也可以通过 pipeline 的方式来优化。

6.复用预索引数据方式来提高 AGG 性能:如通过 terms aggregatio

ns 替代 range aggregations,如要根据年龄来分组,分组目标是:少年(14岁以下)青年(14-28)中年(29-50)老年(51以上),可以在索引的时候设置一个 age_group 字段,预先将数据进行分类。从而不用按 age 来做 range aggregations,通过 agegroup 字段就可以了。

7.Cache 的设置及使用:

(1)QueryCache:ES 查询的时候,使用 filter 查询会使 querycache,如果业务场景中的过滤查询比较多,建议将 querycache 设置大一些,以提高查询速度。indices.queries.cache.size:10%(默认),可设置成百分比,也可设置成具体值,如256mb。当然也可以禁用查询缓存(默认是开启),通过 index.queries.cache.enabled: false 设置。

(2)FieldDataCache:在聚类或排序时,field datacache 会使用频繁,因此,设置字段数据缓存的大小,在聚类或排序场景较多的情形下很有必要,可通过 indices.fielddata.cache.size:30%或具体值10GB 来设置。但是如果场景或数据变更比较频繁,设置 cache 并不是好的做法,因为缓存加载的开销也是特别大的。

(3)ShardRequestCache:查询请求发起后,每个分片会将结果返回给协调节点(Coordinating Node),由协调节点将结果整合。

如果有需求,可以设置开启;通过设置index.requests.cache.enabl

e:true 来开启。不过,shard request cache 只缓存 hits.total,aggre

gations,suggestions 类型的数据,并不会缓存 hits 的内容也可以通过设置 indices.requests.cache.size;1%(默认)来控制缓存空间大小。

 

八、集群运营与恢复

该部分内容之前的课程中已有涉及,此处不多加赘述。

相关实践学习
利用Elasticsearch实现地理位置查询
本实验将分别介绍如何使用Elasticsearch7.10版本进行全文检索、多语言检索和地理位置查询三个Elasticsearch基础检索子场景的实现。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
前端开发 API
ES 高级实战(四)查询 ES 数据
ES 高级实战(四)查询 ES 数据
1307 0
ES 高级实战(四)查询 ES 数据
|
25天前
|
JavaScript 前端开发
ES6-01-简介
ES6-01-简介
8 1
|
2月前
|
JavaScript 前端开发 Java
ES6 简介
ES6 简介
|
10月前
|
JavaScript 前端开发
ES6新增特性学习
ES6新增特性学习
|
11月前
|
JavaScript 前端开发
5个高级ES6特性
5个高级ES6特性
|
12月前
|
自然语言处理 监控 负载均衡
es技术介绍及其使用场景
Elasticsearch(简称ES)是一个开源的实时分布式搜索和分析引擎,基于Apache Lucene构建而成。它被广泛应用于处理大规模数据、实时索引和搜索、复杂查询以及数据分析和可视化等领域。
458 0
ES文档写入原理
ES文档写入原理
88 0
ES文档写入原理
|
监控 数据可视化 Java
ES 插件概述|学习笔记
快速学习 ES 插件概述。
543 0
ES 插件概述|学习笔记
|
存储 JSON 搜索推荐
ES 简介|学习笔记
快速学习 ES 简介。
100 0
ES 简介|学习笔记
|
存储 API 开发者
ES 核心概念概述 | 学习笔记
快速学习 ES 核心概念概述
125 0
ES 核心概念概述 | 学习笔记