点击上方“方志朋”,选择“设为星标”

回复”666“获取新整理的面试资料

来源:http://tinyurl.com/y4gnzbje

  1. 第一部分:调优索引速度

  2. 第二部分-调优搜索速度

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


英文原文:https://www.elastic.co/guide/en/elasticsearch/reference/current/how-to.html

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

第一部分:调优索引速度

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

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

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

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

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

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

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

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

  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 密集的,此时,你需要 a.为filesystem cache分配更多的内存 b.使用SSD硬盘 c.使用local storage(不要使用NFS、SMB 等remote filesystem) d.亚马逊的 弹性块存储(Elastic Block Storage)也是极好的,当然,和local storage比起来,它还是要慢点 如果你的搜索是 CPU-密集的,买好的CPU吧

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

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

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

  2. 剩下的,再去看看 “调优 磁盘使用”吧 (https://www.elastic.co/guide/en/elasticsearch/reference/current/tune-for-disk-usage.html)中有许多磁盘使用策略也提高了索引速度。

第二部分-调优搜索速度

  1. filesystem cache越大越好 为了使得搜索速度更快, es严重依赖filesystem cache 一般来说,需要至少一半的 可用内存 作为filesystem cache,这样es可以在物理内存中 保有 索引的热点区域(hot regions of the index)

  2. 用更好的硬件 搜索一般是I/O bound的,此时,你需要 a.为filesystem cache分配更多的内存 b.使用SSD硬盘 c.使用local storage(不要使用NFS、SMB 等remote filesystem) d.亚马逊的 弹性块存储(Elastic Block Storage)也是极好的,当然,和local storage比起来,它还是要慢点 如果你的搜索是 CPU-bound,买好的CPU吧

  3. 文档模型(document modeling) 文档需要使用合适的类型,从而使得 search-time operations 消耗更少的资源。咋作呢?答:避免 join操作。具体是指 a.nested 会使得查询慢 好几倍 b.parent-child关系 更是使得查询慢几百倍 如果 无需join 能解决问题,则查询速度会快很多

  4. 预索引 数据 根据“搜索数据最常用的方式”来最优化索引数据的方式 举个例子:所有文档都有price字段,大部分query 在 fixed ranges 上运行 range aggregation。你可以把给定范围的数据 预先索引下。然后,使用 terms aggregation

  5. Mappings(能用 keyword 最好了) 数字类型的数据,并不意味着一定非得使用numeric类型的字段。一般来说,存储标识符的 字段(书号ISBN、或来自数据库的 标识一条记录的 数字),使用keyword更好(integer,long 不好哦,亲) 6.避免运行脚本 一般来说,脚本应该避免。如果他们是绝对需要的,你应该使用painless和expressions引擎。

  6. 搜索rounded 日期 日期字段上使用now,一般来说不会被缓存。但,rounded date则可以利用上query cache rounded到分钟等

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

  8. 预热 全局序数(global ordinals) 全局序数 用于 在 keyword字段上 运行 terms aggregations es不知道 哪些fields 将 用于/不用于 term aggregation,因此 全局序数 在需要时才加载进内存 但,可以在mapping type上,定义 eager_global_ordinals==true,这样,refresh时就会加载 全局序数

  9. 预热 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号性能因子。同时,要注意,没有副本的设置在发生单个节点故障的情况下会出现故障,因此在吞吐量和可用性之间进行权衡。

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

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

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

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

2、避免 大的doc。即,单个doc 小了 会更好 given that(考虑到) http.max_context_length默认==100MB,es拒绝索引操作100MB的文档。当然你可以提高这个限制,但,Lucene本身也有限制的,其为2GB 即使不考虑上面的限制,大的doc 会给 network/memory/disk带来更大的压力;a.任何搜索请求,都需要获取 _id 字段,由于filesystem cache工作方式。即使它不请求 _source字段,获取大doc _id 字段消耗更大 b.索引大doc时消耗内存会是 doc本身大小 的好几倍 c.大doc的 proximity search, highlighting 也更加昂贵。它们的消耗直接取决于doc本身的大小

3、避免 稀疏 a.不相关数据 不要 放入同一个索引 b.一般化文档结构(Normalize document structures) c.避免类型 d.在 稀疏 字段上,禁用 norms & doc_values 属性

稀疏为什么不好?Lucene背后的数据结构 更擅长处理 紧凑的数据 text类型的字段,norms默认开启;numerics, date, ip, keyword,doc_values默认开启 Lucene内部使用 integer的doc_id来标识文档 和 内部API交互。举个例子:使用match查询时生成doc_id的迭代器,这些doc_id被用于获取它们的norm,以便计算score。当前的实现是每个doc中保留一个byte用于存储norm值。获取norm值其实就是读取doc_id位置处的一个字节 这非常高效,Lucene通过此值可以快速访问任何一个doc的norm值;但,给定一个doc,即使某个field没有值,仍需要为此doc的此field保留一个字节 doc_values也有同样的问题。2.0之前的fielddata被现在的doc_values所替代了。稀疏性 最明显的影响是 对存储的需求(任何doc的每个field,都需要一个byte);但是呢,稀疏性 对 索引速度和查询速度 也是有影响的,因为:即使doc并没有某些字段值,但,索引时,依然需要写这些字段,查询时,需要skip这些字段的值 某个索引中拥有少量稀疏字段,这完全没有问题。但,这不应该成为常态 稀疏性影响最大的是 norms&doc_values ,但,倒排索引(用于索引 text以及keyword字段),二维点(用于索引geo_point字段)也会受到较小的影响

如何避免稀疏呢?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 属性 a.norms用于计算score,无需score,则可以禁用它(所有filtering字段,都可以禁用norms) b.doc_vlaues用于sort&aggregations,无需这两个,则可以禁用它 但是,不要轻率的做出决定,因为 norms&doc_values无法修改。只能reindex

秘诀1:混合 精确查询和提取词干(mixing exact search with stemming) 对于搜索应用,提取词干(stemming)都是必须的。例如:查询 skiing时,ski和skis都是期望的结果 但,如果用户就是要查询skiing呢?解决方法是:使用multi-field。同一份内容,以两种不同的方式来索引存储 query.simple_query_string.quote_field_suffix,竟然是 查询完全匹配的

秘诀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)上 计算出的 索引统计 并不一致

个人理解:a. 所谓 索引统计 应该就是df,即 doc_freq b. 索引统计 是基于shard来计算的

  1. 搜索时,“已删除”的doc 当然是 永远不会 出现在 结果集中的

  2. 索引统计时,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) 如果你发现

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

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

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

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

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

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

  2. 查询多个索引

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

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

如果数据集较小,则,只使用一个primary shard(es默认是5个),这样两次查询 索引统计 不会变化,因而得分也就一致啦 另一种方式是,将search_type设置为:dfs_query_then_fetech(默认是query_then_fetch) dfs_query_then_fetch的作用是

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

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

  3. coordinating node 要求 所有相关shard 执行 query phase,于是 发出请求,这时,也带上 merged statistics。这样,执行query的shard 将使用 全局的索引统计 大部分情况下,要求 所有相关shard 返回针对当前查询的 索引统计,这是非常cheap的。但,如果查询中 包含 非常大量的 字段/term查询,或者有 fuzzy查询,此时,获取 索引统计 可能并不cheap,因为 为了得到 索引统计 可能 term dictionary 中 所有的term都需要被查询一遍

热门内容:

  • 互联网公司的中年人都去哪了?

  • Github 标星 11.5K!这可能是最好的 Java 博客系统

  • 大批 IDEA 激活码到期之后的乱象...

  • 全面了解 Nginx 主要应用场景

  • 为什么微服务一定要有网关?

  • 那些在一个公司死磕了5-10年的人,最后都怎么样了?

最近面试BAT,整理一份面试资料《Java面试BAT通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。

获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。

明天见(。・ω・。)ノ♡

别再说你不会 ElasticSearch 调优了,都给你整理好了相关推荐

  1. Elasticsearch调优实践

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

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

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

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

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

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

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

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

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

  6. mysql执行计划中性能最差的是_面试中:mysql性能调优-执行计划explain

    mysql的sql调优大家都不陌生,可是调优前都会先看下执行计划,这个是必须的. 插播图片: explain 这个是关键字执行如下: explain select * from user 结果如下: ...

  7. JVM调优总结(7):调优方法

    JVM调优工具 Jconsole,jProfile,VisualVM Jconsole : jdk自带,功能简单,但是可以在系统有一定负荷的情况下使用.对垃圾回收算法有很详细的跟踪.详细说明参考这里 ...

  8. hbase原理与实践_HBase 性能调优第一弹:内存篇

    这是使用 HBase 最不可避免的一个话题,就是 HBase 的性能调优,而且通常建立在我们对 HBase 内部运行机制比较了解的基础上进行的,因此无论怎么说,调优这块都是一个相对复杂的事情.这一篇我 ...

  9. MySQL 服务端调优

    如今,开发人员不断地开发和部署使用 LAMP(Linux®.Apache.MySQL 和 PHP/Perl)架构的应用程序.但是,服务器管理员常常对应用程序本身没有什么控制能力,因为 应用程序是别人编 ...

最新文章

  1. 迁移 Nexus 软件仓库拾遗
  2. 20181023-3 每周例行报告
  3. DellEMC品牌正式启用50%是上一代的R730对比R74
  4. DL之DNN优化技术:DNN中抑制过拟合/欠拟合、提高泛化能力技术的简介、使用方法、案例应用详细攻略
  5. 两种CSS3圆环进度条详解
  6. EL表达式中获取List中某个元素的值
  7. 安装和使用Glassfish
  8. 数据结构与算法之BFPRT算法
  9. scala常用spark的pom.xml与读取csv为rdd到最终join操作
  10. html body标签
  11. ogg mysql表结构不一致_OGG-01163 Bad column表结构一致、trail文件meta不一致处理
  12. php全局化标签,PHP – 在整个应用程序中使类对象全局化?
  13. 对老年人友好!滴滴开通打车400热线
  14. java 分隔函数split(,-1)的用途
  15. ionic tab(选项卡)
  16. submit常用快捷键
  17. GBase 8s 管理员常用命令
  18. ONF定义的SDN架构
  19. excel数据库_最新技术让excel秒变web数据库
  20. 快速解读Nor Flash Datasheet

热门文章

  1. django教程目录
  2. 关于Vue实例的生命周期created和mounted的区别
  3. vector容器总结.xml
  4. PHP shell模式下执行PHP文件报错
  5. C# 最快的逐一打印斐波那契结果数列的算法
  6. 【转】PendingIntent的总结
  7. Numpy入门教程:02. 索引、切片与迭代
  8. 资料分享:送你一本《数据结构与算法JavaScript描述》电子书!
  9. linux查看文件安全权限,Linux系统下如何查看及修改文件读写权限
  10. 10 个 Python 工程师,9 个不合格!