Elasticsearch学习-搜索调优

系列文章目录

  1. Elasticsearch学习-关于倒排索引、DocValues、FieldData和全局序号
  2. Elasticsearch学习-搜索调优
  3. Elasticsearch学习-Doc原理

0x01 摘要

本文会讲讲es中的4种搜索模式以及该如何选择,还会说一些常用的搜索调优选项。
本文基于ES-2.3.3

0x02 search_type

执行分布式搜索时可以执行不同的执行路径。需要将分布式搜索操作分散到所有相关分片,然后收集所有结果。

分布式搜索中的两个最重要问题:

  • 从每个分片中搜索多少结果
  • 每个分片独立,所以在特定分片上执行查询时不会考虑其他分片的TF。那么如果需要准确的排序就需要从所有分片搜集TF最后再聚合算出全局TF,利用全局TF来在每个分片上执行查询

Elasticsearch非常灵活,允许控制基于每个搜索请求执行的搜索类型。可以通过在查询字符串中设置search_type参数。

在讲解各个搜索选项前,我们先简单说下ES搜索中的相似度算法。

ES 2.x中默认使用的相似度算法叫 TF(词频)/IDF(逆向)文档频率算法:

  • 词频:计算某个词在当前被查询文档里的**某个字段(field)**中出现的频率。出现的频率越高,文档越相关。
  • 逆向文档频率:计算某个词在索引内所有文档中出现的百分数。文档出现的频率越高,它的权重就越低。

由于性能原因, ES 不会计算索引内(统筹所有跨节点分片)所有文档的 IDF ,而是每个分片根据该分片内的所有文档计算一个本地 IDF 。

因为文档一般都是均匀分布存储的,也就是说任意两个分片的 IDF 是基本相同的。但如果有 5 个 foo 文档存于分片 1 ,而第 6 个文档存于分片 2 ,在这种场景下, foo 在一个分片里非常普通(所以不那么重要),但是在另一个分片里非常出现很少(所以会显得更重要)。这些 IDF 之间的差异会导致不正确的结果。

但在实际应用中,这并不是一个问题,本地和全局的 IDF 的差异会随着索引里文档数的增多渐渐消失,在真实世界的数据量下,局部的 IDF 会被迅速均化,所以上述问题并不是相关度被破坏所导致的,而是由于数据太少。

2.1 QUERY_THEN_FETCH(查询后取回,默认选择)

思想:先返回足够、尽量少的信息用来打分排序,然后只返回指定数量的数据content字段
查询执行在所有分片上,但是只有部分必要的信息被返回(而不是整个doc内容)。随后结果被普通排序以及根据size做rank排序,在此基础上只需要去相关的那几个分片请求数据的整个content字段。返回的hits的数量的依据的是用户查询时指定的 size 字段,所以只有这些内容会被获取。

  1. 查询阶段:


  2. 取回阶段

当要搜索的index有大量分片(不是副本数)的时候,用这种方式搜索特别快。

2.2 QUERY_AND_FETCH(查询并且取回,Deprecated)

思想:直接查询所有相关的分片来返回数据,每个分片都查出指定 size 的数据全部返回给调用者,再做合并、排序、返回。查询、传输的数据量 = shard数 * size

注意:一般不要手动指定为此模式。
已经在 ES 2.0.0 版本中被删除,详情点击这里

query_and_fetch(查询并且取回) 搜索类型将查询和取回阶段合并成一个步骤。这是一个内部优化选项,当搜索请求的目标只是一个分片时可以使用,例如指定了 routing(路由选择) 值时。 虽然你可以手动选择使用这个搜索类型,但是这么做基本上不会有什么效果。

2.3 DFS_QUERY_THEN_FETCH

思想:和QUERY_THEN_FETCH思想相同,但DFS_QUERY_THEN_FETCH有一个预查询阶段来从每个相关分片中获取TF词频计算全局TF以获得更准确的相关性评分

注意:一般不要手动指定为此模式,不要在生产环境上使用 DFS_QUERY_THEN_FETCH 。完全没有必要。只要有足够的数据就能保证词频是均匀分布的。没有理由给每个查询额外加上 DFS 这步

dfs 搜索类型有一个预查询的阶段,它会从全部相关的分片里取回IDF来计算全局的IDF。

有时无法按相关度排序并提供简短的重现步骤: 用户索引了一些文档,运行一个简单的查询,然后发现明显低相关度的结果出现在高相关度结果之上。

可以设想,我们在两个主分片上创建了索引和总共 10 个文档,其中 6 个文档有单词 foo 。可能是分片 1 有其中 3 个 foo 文档,而分片 2 有其中另外 3 个文档,换句话说,所有文档是均匀分布存储的。

2.4 DFS_QUERY_AND_FETCH(Deprecated)

思想:和QUERY_AND_FETCH思想相同,但DFS_QUERY_AND_FETCH有一个预查询阶段来从每个相关分片中获取TF词频计算全局TF以获得更准确的相关性评分

注意:一般不要手动指定为此模式
已经在 ES 2.0.0 版本中被删除,详情点击这里

2.5 其他

countscan 已经被废弃了。

0x03 搜索选项

合理配置一些query-string参数能够对搜索效率有很大提升。

3.1 preference

preference 参数允许你控制使用哪个分片或节点来处理搜索请求。她接受如下一些参数 _primary , _primary_first , _local , _only_node:xyz ,_prefer_node:xyz 和 _shards:2,3 。这些参数在文档搜索偏好(search preference)里有详细描述。

然而通常最有用的值是一些随机字符串,它们可以避免结果震荡问题(the bouncing results problem)。

3.2 bouncing results(结果震荡)

想像一下,你正在按照 timestamp 字段来对你的结果排序,并且有两个document有相同的timestamp。由于搜索请求是在所有有效的分片副本间轮询的,这两个document可能在原始分片里是一种顺序,在副本分片里是另一种顺序。(有点类似算法不稳定性)

这就是被称为结果震荡(bouncing results)的问题:用户每次刷新页面,结果顺序会发生变化。避免这个问题方法是对于同一个用户总是使用同一个分片。方法就是使用一个随机字符串例如用户的会话ID(session ID)来设置 preference 参数。

3.3 timeout

通常,协调节点会等待接收所有分片的回答。如果有一个节点遇到问题,它会拖慢整个搜索请求。
timeout 参数告诉协调节点最多等待多久,就可以放弃等待而将已有结果返回。返回部分结果总比什么都没有好。

搜索请求的返回将会指出这个搜索是否超时,以及有多少分片成功答复了:

...
"timed_out":     true,  (1)
"_shards": {"total":      5,"successful": 4,"failed":     1     (2)
}, ...

(1) 搜索请求超时。

(2) 五个分片中有一个没在超时时间内答复。

如果一个分片的所有副本都因为其他原因失败了——也许是因为硬件故障——这个也同样会反映在该答复的_shards 部分里。

3.4 routing

在路由值那节里,我们解释了如何在建立索引时提供一个自定义的 routing 参数(默认是使用_id字段进行映射)来保证所有相关的document(如属于单个用户的document)被存放在一个单独的分片中。在搜索时,你可以指定一个或多个routing 值来限制只搜索那些分片而不是搜索index里的全部分片:

这个技术在设计非常大的搜索系统时就会派上用场。

0x04 聚合查询调优

参考:

  • 详解Elasticsearch的Global Ordinals与High Cardinality
  • Elasticsearch聚合优化 | 聚合速度提升5倍
  • ES官网-terms-aggregation-execution-hint

以下转自作者kennywu76

  • global ordinals方式
    Terms aggregation默认的计算方式并非直观感觉上的先查询,然后在查询结果上直接做聚台。ES假定用户需要聚台的数据集是海量的,如果将查询结果全部读取回来放到内存里计算;内存消耗会非常大。因此ES利用了一种叫做global ordinals的数据结构来对聚合的字段来做bucket分配,这个ordinals用有序的数值来代表字段里唯一的一 个字符串,因此为每个ordinals值分配一个bucke就等同于为每个唯一的term分配了 bucket。之后遍历查询结果的时候,可以将结果映射到各个bucket里,就可以很快的统计出每个bucket埋的文档数了。

    这种计算方式主要开销在构建global ordinals和分配bucket上,如果索引包含的原始文档非常多,查询结果包含的文档也很多,那么默认的这种计算方式是内存消耗最小、速度最快的。

  • execution_hint:map
    如果指定execution_hint:map则会 更改聚合执行的方式,这种方式不需要构造global ordinals ,而是直接将查询结果拿回来在内存里构造一个map来计算,因此在查询结果集很小的情况下会显著的比global ordinals快。

    要注意的是这中间有一个平衡点,当结果集大到一定程度的时候. map的内存开销带来的代价可能就抵消了构造global ordinals的开销,从而比global ordinals更慢,所以需要根据实际情况测试对比一下才能找好平衡点。

0x05 分页

可参考

  • es实现分页查询的几种方式

  • ES深度分页查询详解

  • Search your data » Paginate search results

  • ES分页看这篇就够了

  • page+size 适合少量数据,深分页性能不佳

  • scroll占用内存,对增量数据不太好(使用快照),适合大数据量查询或导出。不能向前翻页

  • search_after是官方推荐的性能最好的向后翻页,向前翻页不行

5.1 深度分页定义

查询数据、取回过程虽然支持使用 from 和 size 参数进行分页,但是要在有限范围内 (within limited)。from+size查询时,每个shard必须构造一个长度为 from+size 的优先队列,全部传回协调节点,随后协调节点需要对shard数量 * (from + size) 个document进行全局排序来找到正确的 size 个document,最后返回客户端。

根据document的数量,shard量以及硬件状况,对10,000到50,000条结果(1,000到 5,000页)深分页是可行的。但是对于很大的 from 值,排序过程将会变得非常繁重(会使用巨大量的CPU,内存和带宽)。因此,强烈不建议使用深分页。

5.2 解决方法

  • scroll
    可以将scan(扫描) 搜索是和 scroll(滚屏) API一起使用,可从Elasticsearch里高效地取回海量结果,而不需要付出深分页的代价。

    为了解决深分页的问题,elasticsearch提出了一个scroll滚动的方式,原理是每次查询后返回一个scroll_id,并根据这个scroll_id进行下一页的查询,可以理解为关系型数据库中的游标。

    具体来说,一个scroll滚屏搜索允许我们做一个初始阶段搜索并且持续批量从Elasticsearch里拉取结果直到没有结果为止。 滚屏搜索会及时制作Index快照,这个快照不会包含任何在初始阶段搜索请求后对index做的修改

    但是,这种scroll方式的缺点是不能够进行反复查询,也就是说,只能进行下一页,不能返回上一页。

  • scan
    深度分页代价最高的部分是对结果的全局排序,但如果禁用排序,就能以很低的代价获得全部返回结果。为达成这个目的,可以采用 scan(扫描) 搜索让Elasticsearch不排序。只要shard里还有结果可以返回,就返回一批结果。

  • scan scroll
    为了使用scan-and-scroll(扫描和滚屏),需要执行一个搜索请求,将search_type 设置 成 scan ,并且传递一个 scroll 参数来告诉Elasticsearch滚屏应该持续多长时间。

GET /old_index/_search?search_type=scan&scroll=1m
{"query": { "match_all": {}},"size":  1000
}

上述请求中,将保持滚屏开启1分钟。 该请求的response中不包含任何命中的结果,而是包含了一个Base-64编码的 _scroll_id(滚屏 id) 字符串。随后就可以使用该_scroll_id 传递给 _search/scroll 末端来获取第一批1000条结果。每次循环获取数据的时候都需要传入上一次scroll response返回的_scroll_id。滚屏的终止时间会在我们每次执行滚屏请求时刷新。

  • search_after
    是官方推荐的性能最好的向后翻页,向前翻页不行

0xFE 总结

本文主要讲了一些搜索时调优选项,希望对大家有帮助。

0xFF 参考文档

Elasticsearch: The Definitive Guide

Elasticsearch学习-搜索调优相关推荐

  1. java虚拟机学习-JVM调优总结-新一代的垃圾回收算法(11)

    java虚拟机学习-深入理解JVM(1) java虚拟机学习-慢慢琢磨JVM(2) java虚拟机学习-慢慢琢磨JVM(2-1)ClassLoader的工作机制 java虚拟机学习-JVM内存管理:深 ...

  2. Elasticsearch原理与调优

    elasticsearch 了解多少,说说你们公司 es 的集群架构,索引数据大小,分片有多少,以及一些调优手段 面试官:想了解应聘者之前公司接触的 ES 使用场景.规模,有没有做过比较大规模的索引设 ...

  3. 小白学习Spark04-Spark调优与调试

    Spark调优与调试 4.1 使用SparkConf配置Spark 4.2 Spark执行的组成部分:作业.任务和步骤 4.3 查找信息 4.3.1 Spark网页用户界面 4.3.2 驱动器进程和执 ...

  4. ElasticSearch es 参数调优

    首先上版本号:ES 版本:6.5.4 一般来说ES 的默认参数已经能够满足大部分场景需求,不需要也不建议我们去调节. 但是根据不同的业务场景我们还是可以做一些系统调优,接下来针对常用的参数总结如下: ...

  5. 蒸汽预测之网格搜索调优模型

    首先,导入所要的库 import warnings warnings.filterwarnings("ignore") import matplotlib.pyplot as pl ...

  6. Elasticsearch学习-Doc与Segment原理

    Elasticsearch学习-Doc与Segment原理 0x00 系列文章目录 Elasticsearch学习-关于倒排索引.DocValues.FieldData和全局序号 Elasticsea ...

  7. Elasticsearch学习-关于倒排索引、DocValues、FieldData和全局序号

    Elasticsearch学习-关于倒排索引.DocValues.FieldData和全局序号 0x00 系列文章目录 Elasticsearch学习-关于倒排索引.DocValues.FieldDa ...

  8. 深度神经网络之Keras(三)——正则化、超参数调优和学习方向

    深度神经网络之Keras(三)--正则化.超参数调优和学习方向 本文将继续探索Keras框架下的深度神经网络知识,主要介绍了利用Keras构建的深度神经网络正则化及超参数调优问题. 目录 深度神经网络 ...

  9. ElasticSearch还能性能调优,涨见识、涨见识了!!!

    ElasticSearch 性能调优 作者: 博学谷狂野架构师 GitHub地址:GitHub地址 (有我们精心准备的130本电子书PDF) 概述 性能优化是个涉及面非常广的问题,不同的环境,不同的业 ...

  10. elasticsearch 学习须知

    人工智能.大数据快速发展的今天,对于 TB 甚至 PB 级大数据的快速检索已然成为刚需.Elasticsearch 作为开源领域的后起之秀,从2010年至今得到飞跃式的发展. Elasticsearc ...

最新文章

  1. 【转】堆栈和托管堆 c#
  2. Angular1.x的自定义指令directive参数配置详细说明
  3. 【运维人员应该掌握哪些常用技术】
  4. python 如何封装dll_如何为DLL库创建Python包装器
  5. cve-2017-12629 apache solr xxe rce 漏洞分析
  6. java-基础练习题3
  7. 晶体封装越小esr越大_SuperFin晶体管技术加持!英特尔新一代10nm可媲美台积电5nm?...
  8. RFE筛选出的特征变量竟然是Boruta的4倍之多
  9. Python calendar日历模块的常用方法
  10. How do I create 2D water with dynamic waves?
  11. 使用Kotlin的Android Spinner
  12. c语言字体取模软件下载,非常好用的lcd汉字取模软件
  13. Python+Opencv检测模糊图片
  14. javascript 属性的特性 二十五
  15. 仿QQ音乐下载歌曲头部导航
  16. 加密IC 在android 机子上的简单应用
  17. java 分析内存_Java 内存查看与分析
  18. 视觉SLAM十四讲学习笔记-第三讲-旋转向量、欧拉角、四元数
  19. 特殊矩阵——n阶对称矩阵
  20. nanodet-plus

热门文章

  1. matlab在点内加入权值,matlab权值矩阵
  2. Win10以太网没有有效的IP配置解决方法
  3. omnet++ 4维的立方体网络仿真
  4. 小程序分账系统是什么?能解决二清吗?
  5. 答疑解惑 | 关于PMBOK第七版,常见问题合集【附电子版】
  6. 深圳-珠海-澳门-香港四日游攻略
  7. 《遥远的救世主》遵守客观规律(三)——文化属性
  8. 我的 OCM 之路|书写无悔青春,追梦永不止步
  9. Python之OpenGL笔记(30):飘扬的旗帜
  10. Matlab之生成间距向量函数linspace和logspace