上一篇:一个90后员工猝死的全过程

0、2T架构师学习资料干货分享

ES官方调优指南

第一部分:调优索引速度

第二部分:调优搜索速度

第三部分:通用的一些建议

ES发布时带有的默认值,可为es的开箱即用带来很好的体验。全文搜索、高亮、聚合、索引文档 等功能无需用户修改即可使用,当你更清楚的知道你想如何使用es后,你可以作很多的优化以提高你的用例的性能,下面的内容告诉你 你应该/不应该 修改哪些配置。

第一部分:调优索引速度

https://www.elastic.co/guide/en/elasticsearch/reference/current/tune-for-indexing-speed.html

使用批量请求批量请求将产生比单文档索引请求好得多的性能。

为了知道批量请求的最佳大小,您应该在具有单个分片的单个节点上运行基准测试。首先尝试索引100个文件,然后是200,然后是400,等等。当索引速度开始稳定时,您知道您达到了数据批量请求的最佳大小。在配合的情况下,最好在太少而不是太多文件的方向上犯错。请注意,如果群集请求太大,可能会使群集受到内存压力,因此建议避免超出每个请求几十兆字节,即使较大的请求看起来效果更好。

发送端使用多worker/多线程向es发送数据 发送批量请求的单个线程不太可能将Elasticsearch群集的索引容量最大化。为了使用集群的所有资源,您应该从多个线程或进程发送数据。除了更好地利用集群的资源,这应该有助于降低每个fsync的成本。

请确保注意TOOMANYREQUESTS(429)响应代码(Java客户端的EsRejectedExecutionException),这是Elasticsearch告诉您无法跟上当前索引速率的方式。发生这种情况时,应该再次尝试暂停索引,理想情况下使用随机指数回退。

与批量调整大小请求类似,只有测试才能确定最佳的worker数量。这可以通过逐渐增加工作者数量来测试,直到集群上的I / O或CPU饱和。

1.调大 refresh interval

默认的index.refresh_interval是1s,这迫使Elasticsearch每秒创建一个新的分段。增加这个价值(比如说30s)将允许更大的部分flush并减少未来的合并压力。

2.加载大量数据时禁用refresh和replicas

如果您需要一次加载大量数据,则应该将index.refreshinterval设置为-1并将index.numberofreplicas设置为0来禁用刷新。这会暂时使您的索引处于危险之中,因为任何分片的丢失都将导致数据 丢失,但是同时索引将会更快,因为文档只被索引一次。初始加载完成后,您可以将index.refreshinterval和index.numberofreplicas设置回其原始值。

3.设置参数,禁止OS将es进程swap出去

您应该确保操作系统不会swapping out the java进程,通过禁止swap (https://www.elastic.co/guide/en/elasticsearch/reference/current/setup-configuration-memory.html)

4.为filesystem cache分配一半的物理内存

文件系统缓存将用于缓冲I / O操作。您应该确保将运行Elasticsearch的计算机的内存至少减少到文件系统缓存的一半。

5.使用自动生成的id(auto-generated ids)

索引具有显式id的文档时,Elasticsearch需要检查具有相同id的文档是否已经存在于相同的分片中,这是昂贵的操作,并且随着索引增长而变得更加昂贵。通过使用自动生成的ID,Elasticsearch可以跳过这个检查,这使索引更快。

6.买更好的硬件

搜索一般是I/O 密集的,此时,你需要

  1. 为filesystem cache分配更多的内存

  2. 使用SSD硬盘

  3. 使用local storage(不要使用NFS、SMB 等remote filesystem)

  4. 亚马逊的 弹性块存储(Elastic Block Storage)也是极好的,当然,和local storage比起来,它还是要慢点

如果你的搜索是 CPU-密集的,买好的CPU吧

7.加大 indexing buffer size

如果你的节点只做大量的索引,确保index.memory.indexbuffersize足够大,每个分区最多可以提供512 MB的索引缓冲区,而且索引的性能通常不会提高。Elasticsearch采用该设置(java堆的一个百分比或绝对字节大小),并将其用作所有活动分片的共享缓冲区。非常活跃的碎片自然会使用这个缓冲区,而不是执行轻量级索引的碎片。

默认值是10%,通常很多:例如,如果你给JVM 10GB的内存,它会给索引缓冲区1GB,这足以承载两个索引很重的分片。

8.禁用fieldnames字段

fieldnames字段引入了一些索引时间开销,所以如果您不需要运行存在查询,您可能需要禁用它。(fieldnames:https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-field-names-field.html)

9.剩下的,再去看看 “调优 磁盘使用”吧

(https://www.elastic.co/guide/en/elasticsearch/reference/current/tune-for-disk-usage.html)中有许多磁盘使用策略也提高了索引速度。另外,MySQL 系列面试题和答案全部整理好了,微信搜索互联网架构师,在后台发送:2T,可以在线阅读。

第二部分-调优搜索速度

1.filesystem cache越大越好

为了使得搜索速度更快, es严重依赖filesystem cache

一般来说,需要至少一半的 可用内存 作为filesystem cache,这样es可以在物理内存中 保有 索引的热点区域(hot regions of the index)

2.用更好的硬件

搜索一般是I/O bound的,此时,你需要

  • 为filesystem cache分配更多的内存

  • 使用SSD硬盘

  • 使用local storage(不要使用NFS、SMB 等remote filesystem)

  • 亚马逊的 弹性块存储(Elastic Block Storage)也是极好的,当然,和local storage比起来,它还是要慢点

如果你的搜索是 CPU-bound,买好的CPU吧

3.文档模型(document modeling)

文档需要使用合适的类型,从而使得 search-time operations 消耗更少的资源。咋作呢?答:避免 join操作。具体是指

  • nested 会使得查询慢 好几倍

  • parent-child关系 更是使得查询慢几百倍

如果 无需join 能解决问题,则查询速度会快很多

4.预索引 数据

根据“搜索数据最常用的方式”来最优化索引数据的方式

举个例子:所有文档都有price字段,大部分query 在 fixed ranges 上运行 range aggregation。你可以把给定范围的数据 预先索引下。然后,使用 terms aggregation

5.Mappings(能用 keyword 最好了)

数字类型的数据,并不意味着一定非得使用numeric类型的字段。

一般来说,存储标识符的 字段(书号ISBN、或来自数据库的 标识一条记录的 数字),使用keyword更好(integer,long 不好哦,亲)

6.避免运行脚本

一般来说,脚本应该避免。如果他们是绝对需要的,你应该使用painless和expressions引擎。

7.搜索rounded 日期

日期字段上使用now,一般来说不会被缓存。但,rounded date则可以利用上query cache

rounded到分钟等

8.强制merge只读的index

只读的index可以从“merge成 一个单独的 大segment”中收益

9.预热 全局序数(global ordinals)

全局序数 用于 在 keyword字段上 运行 terms aggregations

es不知道 哪些fields 将 用于/不用于 term aggregation,因此 全局序数 在需要时才加载进内存

但,可以在mapping type上,定义 eagerglobalordinals==true,这样,refresh时就会加载 全局序数

10.预热 filesystem cache

机器重启时,filesystem cache就被清空。OS将index的热点区域(hot regions of the index)加载进filesystem cache是需要花费一段时间的。

设置 index.store.preload 可以告知OS 这些文件需要提早加载进入内存

11.使用索引排序来加速连接

索引排序对于以较慢的索引为代价来加快连接速度非常有用。在索引分类文档中关于它的信息。

12.使用preference来优化高速缓存利用率

有多个缓存可以帮助提高搜索性能,例如文件系统缓存,请求缓存或查询缓存。然而,所有这些缓存都维护在节点级别,这意味着如果连续运行两次相同的请求,则有一个或多个副本,并使用循环(默认路由算法),那么这两个请求将转到不同的分片副本,阻止节点级别的缓存帮助。

由于搜索应用程序的用户一个接一个地运行类似的请求是常见的,例如为了分析索引的较窄的子集,使用标识当前用户或会话的优选值可以帮助优化高速缓存的使用。

13.副本可能有助于吞吐量,但不会一直存在

除了提高弹性外,副本可以帮助提高吞吐量。例如,如果您有单个分片索引和三个节点,则需要将副本数设置为2,以便共有3个分片副本,以便使用所有节点。

现在假设你有一个2-shards索引和两个节点。在一种情况下,副本的数量是0,这意味着每个节点拥有一个分片。在第二种情况下,副本的数量是1,这意味着每个节点都有两个碎片。哪个设置在搜索性能方面表现最好?通常情况下,每个节点的碎片数少的设置将会更好。

原因在于它将可用文件系统缓存的份额提高到了每个碎片,而文件系统缓存可能是Elasticsearch的1号性能因子。同时,要注意,没有副本的设置在发生单个节点故障的情况下会出现故障,因此在吞吐量和可用性之间进行权衡。

那么复制品的数量是多少?如果您有一个具有numnodes节点的群集,那么numprimaries总共是主分片,如果您希望能够一次处理maxfailures节点故障,那么正确的副本数是max(maxfailures,ceil(numnodes / numprimaries) - 1)。

14.打开自适应副本选择

当存在多个数据副本时,elasticsearch可以使用一组称为自适应副本选择的标准,根据包含分片的每个副本的节点的响应时间,服务时间和队列大小来选择数据的最佳副本。这可以提高查询吞吐量并减少搜索量大的应用程序的延迟。

第三部分:通用的一些建议

1、不要 返回大的结果集

es设计来作为搜索引擎,它非常擅长返回匹配query的top n文档。但,如“返回满足某个query的 所有文档”等数据库领域的工作,并不是es最擅长的领域。如果你确实需要返回所有文档,你可以使用Scroll API

2、避免 大的doc。即,单个doc 小了 会更好

given that(考虑到) http.maxcontextlength默认==100MB,es拒绝索引操作100MB的文档。当然你可以提高这个限制,但,Lucene本身也有限制的,其为2GB 即使不考虑上面的限制,大的doc 会给 network/memory/disk带来更大的压力;

  • 任何搜索请求,都需要获取 _id 字段,由于filesystem cache工作方式。即使它不请求 _source字段,获取大doc _id 字段消耗更大

  • 索引大doc时消耗内存会是 doc本身大小 的好几倍

  • 大doc的 proximity search, highlighting 也更加昂贵。它们的消耗直接取决于doc本身的大小

3、避免 稀疏

  • 不相关数据 不要 放入同一个索引

  • 一般化文档结构(Normalize document structures)

  • 避免类型

  • 在 稀疏 字段上,禁用 norms & doc_values 属性

稀疏为什么不好?

Lucene背后的数据结构 更擅长处理 紧凑的数据

text类型的字段,norms默认开启;numerics, date, ip, keyword,docvalues默认开启 Lucene内部使用 integer的docid来标识文档 和 内部API交互。

举个例子:使用match查询时生成docid的迭代器,这些docid被用于获取它们的norm,以便计算score。当前的实现是每个doc中保留一个byte用于存储norm值。获取norm值其实就是读取doc_id位置处的一个字节

这非常高效,Lucene通过此值可以快速访问任何一个doc的norm值;但,给定一个doc,即使某个field没有值,仍需要为此doc的此field保留一个字节

docvalues也有同样的问题。2.0之前的fielddata被现在的docvalues所替代了。

稀疏性 最明显的影响是 对存储的需求(任何doc的每个field,都需要一个byte);但是呢,稀疏性 对 索引速度和查询速度 也是有影响的,因为:即使doc并没有某些字段值,但,索引时,依然需要写这些字段,查询时,需要skip这些字段的值

某个索引中拥有少量稀疏字段,这完全没有问题。但,这不应该成为常态

稀疏性影响最大的是 norms&docvalues ,但,倒排索引(用于索引 text以及keyword字段),二维点(用于索引geopoint字段)也会受到较小的影响。另外,关注公众号互联网架构师,在后台回复:2T,可以获取我整理的 Java 系列面试题和答案,非常齐全。

如何避免稀疏呢?

1、不相关数据 不要 放入同一个索引 给个tip:索引小(即:doc的个数较少),则,primary shard也要少

2、一般化文档结构(Normalize document structures)

3、避免类型(Avoid mapping type) 同一个index,最好就一个mapping type。在同一个index下面,使用不同的mapping type来存储数据,听起来不错,但,其实不好。given that(考虑到)每一个mapping type会把数据存入 同一个index,因此,多个不同mapping type,各个的field又互不相同,这同样带来了稀疏性 问题

4、在 稀疏 字段上,禁用 norms & doc_values 属性

  • norms用于计算score,无需score,则可以禁用它(所有filtering字段,都可以禁用norms)

  • docvlaues用于sort&aggregations,无需这两个,则可以禁用它 但是,不要轻率的做出决定,因为 norms&docvalues无法修改。只能reindex

秘诀1:混合 精确查询和提取词干(mixing exact search with stemming)

对于搜索应用,提取词干(stemming)都是必须的。例如:查询 skiing时,ski和skis都是期望的结果

但,如果用户就是要查询skiing呢?

解决方法是:使用multi-field。同一份内容,以两种不同的方式来索引存储 query.simplequerystring.quotefieldsuffix,竟然是 查询完全匹配的

秘诀2:获取一致性的打分

score不能重现 同一个请求,连续运行2次,但,两次返回的文档顺序不一致。这是相当坏的用户体验

如果存在 replica,则就可能发生这种事,这是因为:search时,replication group中的shard是按round-robin方式来选择的,因此两次运行同样的请求,请求如果打到 replication group中的不同shard,则两次得分就可能不一致

那问题来了,“你不是整天说 primary和replica是in-sync的,是完全一致的”嘛,为啥打到“in-sync的,完全一致的shard”却算出不同的得分?

原因就是标注为“已删除”的文档。如你所知,doc更新或删除时,旧doc并不删除,而是标注为“已删除”,只有等到 旧doc所在的segment被merge时,“已删除”的doc才会从磁盘删除掉

索引统计(index statistic)是打分时非常重要的一部分,但,由于 deleted doc 的存在,在同一个shard的不同copy(即:各个replica)上 计算出的 索引统计 并不一致

个人理解:

  • 所谓 索引统计 应该就是df,即 doc_freq

  • 索引统计 是基于shard来计算的

搜索时,“已删除”的doc 当然是 永远不会 出现在 结果集中的 索引统计时,for practical reasons,“已删除”doc 依然是统计在内的

假设,shard A0 刚刚完成了一次较大的segment merge,然后移除了很多“已删除”doc,shard A1 尚未执行 segment merge,因此 A1 依然存在那些“已删除”doc

于是:两次请求打到 A0 和 A1 时,两者的 索引统计 是显著不同的

如何规避 score不能重现 的问题?使用 preference 查询参数

发出搜索请求时候,用 标识字符串 来标识用户,将 标识字符串 作为查询请求的preference参数。这确保多次执行同一个请求时候,给定用户的请求总是达到同一个shard,因此得分会更为一致(当然,即使同一个shard,两次请求 跨了 segment merge,则依然会得分不一致)

这个方式还有另外一个优点,当两个doc得分一致时,则默认按着doc的 内部Lucene doc id 来排序(注意:这并不是es中的 _id 或 _uid)。但是呢,shard的不同copy间,同一个doc的 内部Lucene doc id 可能并不相同。因此,如果总是达到同一个shard,则,具有相同得分的两个doc,其顺序是一致的

score错了

score错了(Relevancy looks wrong)

如果你发现

  • 具有相同内容的文档,其得分不同

  • 完全匹配 的查询 并没有排在第一位 这可能都是由 sharding 引起的

  • 默认情况下,搜索文档时,每个shard自己计算出自己的得分。

  • 索引统计 又是打分时一个非常重要的因素。

如果每个shard的 索引统计相似,则 搜索工作的很好

文档是平分到每个primary shard的,因此 索引统计 会非常相似,打分也会按着预期工作。但,万事都有个但是:

  • 索引时使用了 routing(文档不能平分到每个primary shard 啦)

  • 查询多个索引

  • 索引中文档的个数 非常少

这会导致:参与查询的各个shard,各自的 索引统计 并不相似(而,索引统计对 最终的得分 又影响巨大),于是 打分出错了(relevancy looks wrong)

那,如何绕过 score错了(Relevancy looks wrong)?

如果数据集较小,则,只使用一个primary shard(es默认是5个),这样两次查询 索引统计 不会变化,因而得分也就一致啦

另一种方式是,将searchtype设置为:dfsquerythenfetech(默认是querythenfetch)

dfsquerythen_fetch的作用是

  • 向 所有相关shard 发出请求,要求 所有相关shard 返回针对当前查询的 索引统计

  • 然后,coordinating node 将 merge这些 索引统计,从而得到 merged statistics

  • coordinating node 要求 所有相关shard 执行 query phase,于是 发出请求,这时,也带上 merged statistics。这样,执行query的shard 将使用 全局的索引统计

大部分情况下,要求 所有相关shard 返回针对当前查询的 索引统计,这是非常cheap的。但,如果查询中 包含 非常大量的 字段/term查询,或者有 fuzzy查询,此时,获取 索引统计 可能并不cheap,因为 为了得到 索引统计 可能 term dictionary 中 所有的term都需要被查询一遍。另外,关注公众号互联网架构师,在后台回复:2T,可以获取我整理的 Java 系列面试题和答案,非常齐全。

英文原文:https://www.elastic.co/guide/en/elasticsearch/reference/current/how-to.html
译者:Ghost Stories
来源:http://wangnan.tech/post/elasticsearch-how-to

看完这篇文章,你有什么收获?欢迎在留言区与10w+Java开发者一起讨论~

最后,关注公众号互联网架构师,在后台回复:2T,可以获取我整理和创作的 Java 系列教程非常齐全。

推荐阅读

1、2019 年 9 月全国程序员工资统计,你是什么水平?

2、如何才能成为优秀的架构师?

3、从零开始搭建创业公司后台技术栈

4、程序员一般可以从什么平台接私活?

5、37岁程序员被裁,120天没找到工作,无奈去小公司,结果懵了...

6、滴滴业务中台构建实践,首次曝光

7、不认命,从10年流水线工人,到谷歌上班的程序媛,一位湖南妹子的励志故事

8、15张图看懂瞎忙和高效的区别!

30 个 ElasticSearch 调优知识点,都给你整理好了!相关推荐

  1. 别再说你不会 ElasticSearch 调优了,都给你整理好了

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 来源:http://tinyurl.com/y4gnzbje 第一 ...

  2. Elasticsearch调优实践

      背景 Elasticsearch(ES)作为NOSQL+搜索引擎的有机结合体,不仅有近实时的查询能力,还具有强大的聚合分析能力.因此在全文检索.日志分析.监控系统.数据分析等领域ES均有广泛应用. ...

  3. 为什么对 Java 性能调优最后都像在调 you?

    不知道你有没有发现,优化Java,或者任何其他语言的代码性能经常被当做是一种暗黑艺术. 性能分析有种神秘感.画面类似是这样的:一个「黑客」经过多年练就的手艺,能够快速深入了解某个系统,并提出神奇的解决 ...

  4. Java程序员涨薪必备的性能调优知识点,收好了!

    Java 应用性能优化是一个老生常谈的话题,典型的性能问题如页面响应慢.接口超时,服务器负载高.并发数低,数据库频繁死锁等.尤其是在"糙快猛"的互联网开发模式大行其道的今天,随着系 ...

  5. 【运维技术面试】nginx调优你都做过哪些?

    这个问题也是在运维面试中经常问的一个问题. 这样的问题,我们该怎么回答呢? 一般情况下,类似于这样的问题,一定要回答的全面一点. 这里的全面并不是技术上的全面,而是你对nginx的理解的全面. 比如, ...

  6. 【Elasticsearch】索引和查询性能调优的21条建议-以及调优参数

    文章目录 1.概述 1.Elasticsearch部署建议 1.1. 选择合理的硬件配置:尽可能使用 SSD 1.2. 给JVM配置机器一半的内存,但是不建议超过32G 1.3. 规模较大的集群配置专 ...

  7. 【SQL性能优化】当我们思考数据库调优的时候,都有哪些维度可以选择?

    文章目录 数据库调优的目标 用户的反馈 日志分析 服务器资源使用监控 数据库内部状况监控 对数据库进行调优,都有哪些维度可以进行选择? 第一步,选择适合的 DBMS 第二步,优化表设计 第三步,优化逻 ...

  8. “性能调优”坑惨了几十万程序员

    很多程序员觉得性能调优这块的JVM.Mysql不是什么大事,自己平时写代码写得好好的,不是很了解JVM好像也没什么的,认为得千万级甚至亿万级的大流量.大项目才用得上,其他一般场景根本用不到,直到遇见这 ...

  9. 性能监控/优化系列——JVM监控/调优

    JVM监控 1. ParNew表示CMS收集器在新生代采用多线程进行垃圾回收.DefNew表示顺序垃圾收集器在新生代采用单线程进行垃圾回收. 2.系统做完CMS cycle后,观察minorGC的日志 ...

  10. ambari_HDP之mapreduce参数调优

    一.基础环境 基础环境: centos6.8 ambari版本: 2.2.1 HDP版本: 2.3.2.0 HDP的默认配置文件:(本文以ambari-2.2.1为例): 配置文件目录:/usr/hd ...

最新文章

  1. Scala 中将方法、函数、函数式编程和面向对象编程关系分析图
  2. ext js gridpanel绑定到动态生成的store
  3. linux pxe启动ftp格式,FTP+DHCP+TFTP+PXElinux实现RHLINUX的网络自动安装
  4. Effective Java~44. 坚持使用标准的函数接口
  5. leetcode算法—无重复字符的最长子串 Longest Substring Without Repeating Characters
  6. cookie不同页面访问不到的问题
  7. 蓝桥杯Java组常用算法与技巧
  8. 2000-2018年各省能源消费和碳排放数据数据、1997-2017年各省地级市县区碳排放数、各国二氧化碳排放量(人均公吨数)1960-2014年、二氧化碳排放量、各省市碳排放权额分配实施方案
  9. 《天长地久》写照真实生活为何被影迷埋没不被欣赏
  10. 简单图形验证码的识别
  11. Google Safe Browsing API的实施
  12. 大学毕业生找不到工作的原因何在?
  13. 超好的数据结构算法可视化网站
  14. android系统中区分UDisk和SDCard
  15. python遗传算法_带有Python的AI –遗传算法
  16. Android 一种关于解决 No view found for id xxxx for fragment xxxx 问题的方案
  17. 漫画 | 到底是什么让IT人如此苦逼???
  18. 数据分析:大数据时代的必备技能之Tableau
  19. python index out of bounds_错误:索引2超出大小为1的轴0的界限
  20. linux 的图形编程基础,linux 图形界面编程基础

热门文章

  1. 李佳琦618直播清单都在这张思维导图上了
  2. 教你正确设置CrossOver的Wine配置(二)
  3. jq 实现头像(气泡式浮动)
  4. 夏日葵电商:从5大方面谈微信商城怎样提高用户体验度
  5. 【LeetCode】141. Linked List Cycle (2 solutions)
  6. Android开发学习笔记:数据存取之File浅析
  7. 现任明教教主 NAC Framework EOU 视频
  8. 人生苦短,我用VIM!
  9. 「leetcode」101. 对称二叉树
  10. Flutter第七期 - 布局总结篇