原文链接:https://www.elastic.co/guide/cn/elasticsearch/guide/current/_preventing_combinatorial_explosions.html

优化聚合查询

“elasticsearch 里面桶的叫法和 SQL 里面分组的概念是类似的,一个桶就类似 SQL 里面的一个 group,多级嵌套的 aggregation, 类似 SQL 里面的多字段分组(group by field1,field2, ……),注意这里仅仅是概念类似,底层的实现原理是不一样的。 -译者注”

terms 桶基于我们的数据动态构建桶;它并不知道到底生成了多少桶。 大多数时候对单个字段的聚合查询还是非常快的, 但是当需要同时聚合多个字段时,就可能会产生大量的分组,最终结果就是占用 es 大量内存,从而导致 OOM 的情况发生。

假设我们现在有一些关于电影的数据集,每条数据里面会有一个数组类型的字段存储表演该电影的所有演员的名字。

{"actors" : ["Fred Jones","Mary Jane","Elizabeth Worthing"]
}

如果我们想要查询出演影片最多的十个演员以及与他们合作最多的演员,使用聚合是非常简单的:

{"aggs" : {"actors" : {"terms" : {"field" : "actors","size" :  10},"aggs" : {"costars" : {"terms" : {"field" : "actors","size" :  5}}}}}
}

这会返回前十位出演最多的演员,以及与他们合作最多的五位演员。这看起来是一个简单的聚合查询,最终只返回 50 条数据!

但是, 这个看上去简单的查询可以轻而易举地消耗大量内存,我们可以通过在内存中构建一个树来查看这个 terms 聚合。 actors 聚合会构建树的第一层,每个演员都有一个桶。然后,内套在第一层的每个节点之下, costar 聚合会构建第二层,每个联合出演一个桶,请参见 图 42 “Build full depth tree” 所示。这意味着每部影片会生成 n2 个桶!

用真实点的数据,设想平均每部影片有 10 名演员,每部影片就会生成 102 == 100 个桶。如果总共有 20,000 部影片,粗率计算就会生成 2,000,000 个桶。

现在,记住,聚合只是简单的希望得到前十位演员和与他们联合出演者,总共 50 条数据。为了得到最终的结果,我们创建了一个有 2,000,000 桶的树,然后对其排序,取 top10。 图 图 43 “Sort tree” 和图 图 44 “Prune tree” 对这个过程进行了阐述。


这时我们一定非常抓狂,在 2 万条数据下执行任何聚合查询都是毫无压力的。如果我们有 2 亿文档,想要得到前 100 位演员以及与他们合作最多的 20 位演员,作为查询的最终结果会出现什么情况呢?

可以推测聚合出来的分组数非常大,会使这种策略难以维持。世界上并不存在足够的内存来支持这种不受控制的聚合查询。

深度优先与广度优先(Depth-First Versus Breadth-First)

Elasticsearch 允许我们改变聚合的 集合模式 ,就是为了应对这种状况。 我们之前展示的策略叫做 深度优先 ,它是默认设置, 先构建完整的树,然后修剪无用节点。 深度优先 的方式对于大多数聚合都能正常工作,但对于如我们演员和联合演员这样例子的情形就不太适用。

为了应对这些特殊的应用场景,我们应该使用另一种集合策略叫做 广度优先 。这种策略的工作方式有些不同,它先执行第一层聚合, 再 继续下一层聚合之前会先做修剪。 图 图 45 “Build first level” 和图 图 47 “Prune first level” 对这个过程进行了阐述。

在我们的示例中, actors 聚合会首先执行,在这个时候,我们的树只有一层,但我们已经知道了前 10 位的演员!这就没有必要保留其他的演员信息,因为它们无论如何都不会出现在前十位中。



因为我们已经知道了前十名演员,我们可以安全的修剪其他节点。修剪后,下一层是基于 它的 执行模式读入的,重复执行这个过程直到聚合完成,如图 图 48 “Populate full depth for remaining nodes” 所示。 这种场景下,广度优先可以大幅度节省内存。

要使用广度优先,只需简单 的通过参数 collect 开启:

{"aggs" : {"actors" : {"terms" : {"field" :        "actors","size" :         10,"collect_mode" : "breadth_first" },"aggs" : {"costars" : {"terms" : {"field" : "actors","size" :  5}}}}}
}

广度优先仅仅适用于每个组的聚合数量远远小于当前总组数的情况下,因为广度优先会在内存中缓存裁剪后的仅仅需要缓存的每个组的所有数据,以便于它的子聚合分组查询可以复用上级聚合的数据。

广度优先的内存使用情况与裁剪后的缓存分组数据量是成线性的。对于很多聚合来说,每个桶内的文档数量是相当大的。 想象一种按月分组的直方图,总组数肯定是固定的,因为每年只有12个月,这个时候每个月下的数据量可能非常大。这使广度优先不是一个好的选择,这也是为什么深度优先作为默认策略的原因。

针对上面演员的例子,如果数据量越大,那么默认的使用深度优先的聚合模式生成的总分组数就会非常多,但是预估二级的聚合字段分组后的数据量相比总的分组数会小很多所以这种情况下使用广度优先的模式能大大节省内存,从而通过优化聚合模式来大大提高了在某些特定场景下聚合查询的成功率。

Elasticsearch聚合性能优化:深度优先和广度优先相关推荐

  1. 【Elasticsearch】es Elasticsearch 聚合性能优化六大猛招

    1.概述 参考:Elasticsearch 聚合性能优化六大猛招

  2. Elasticsearch 聚合性能优化六大猛招

    Elasticsearch 最少必要知识实战教程直播回放 1.问题引出 默认情况下,Elasticsearch 已针对大多数用例进行了优化,确保在写入性能和查询性能之间取得平衡.我们将介绍一些聚合性能 ...

  3. Elasticsearch 检索性能优化实战指南

    1.当我们在说 Elasticsearch 检索性能优化的时候,实际在说什么?! 检索响应慢! 并发检索用户多时,响应时间不达标 卡死了! 怎么还没有出结果? 怎么这么慢? 为啥竞品产品的很快就返回结 ...

  4. Elasticsearch 技术分析(七): Elasticsearch 的性能优化

    硬件选择 Elasticsearch(后文简称 ES)的基础是 Lucene,所有的索引和文档数据是存储在本地的磁盘中,具体的路径可在 ES 的配置文件../config/elasticsearch. ...

  5. 监控日志loging Elasticsearch(性能优化八)

    在当今世界,各行各业每天都有海量数据产生,为了从这些海量数据中获取想要的分析结果,需要对数据进行提取.转换,存储,维护,管理和分析. 这已然远远超出了普通处理工具.数据库等的实现能力,只有基于的分布式 ...

  6. FLink聚合性能优化--MiniBatch分析

    文章目录 一.MiniBatch的演进思路 1.MiniBatch版本 2.适用场景 3.普通聚合与MiniBatch聚合对比 A.Simple Aggregation普通聚合 B.MiniBatch ...

  7. Elasticsearch查询性能优化

    constant_score的用处 当我们不关心检索词频率TF(Term Frequency)对搜索结果排序的影响时,可以使用constant_score将查询语句query或者过滤语句filter包 ...

  8. vue--百度地图之离线地图--大量标注点造成卡顿问题--海量点聚合性能优化

    如果你啥都不想看,只想解决问题,直接跳转–四.步骤 目录 一.需求 二.地图的引入.聚合点的使用 1.如图:引入百度地图和其他相关插件(按需引入,这些百度地图官网上都可以下载到) 2.初始化地图准备: ...

  9. Elasticsearch聚合——Bucket Aggregations

    2019独角兽企业重金招聘Python工程师标准>>> 本文主要参考于Elasticsearch Reference 6.3 -- Bucket Aggregations Terms ...

最新文章

  1. 外部引用CSS中 link与@import的区别
  2. 揭开不一样的世界,这5部纪录片绝对不能错过!
  3. python log日志级别_python – 日志记录:如何为处理程序设置最大日志级别
  4. 业务场景下数据采集机制和策略
  5. Python大数据系列-01-关系数据库基本运算
  6. MySQL中视图和触发器学习
  7. 40款免费社交图标素材
  8. C# WinForm 使用FlowLayoutPanel控件做为导航菜单按钮的容器
  9. MySQL数据监控案例_zabbix 监控多实例mysql
  10. dplayer安装php_Dplayer播放器集成p2p加速源码分享
  11. PDF编辑器里的测量工具如何使用?
  12. 服务器里怎么设置微信多开,企业微信多开的4种方法
  13. 使用Origin绘制柱状图(入门)
  14. python学习日常-----作业(4)
  15. Altium Designer 18 生成网络表
  16. qt跨平台软件开发_Qt on Mobile:跨平台应用程序开发的最佳实践
  17. 管程法----生产者和消费者
  18. 笔记:期权定价-无套利理论
  19. 海康摄像头实现点位缩放功能(切换焦距)
  20. 所生成项目的处理器架构“MSIL”与引用“***”的处理器架构“x86”不匹配。这种不匹配可能会导致运行时失败。请考虑通过配置管理器更改您的项目的目标处理器架构,以使您的项目与引用间的处理器架构...

热门文章

  1. 1634: Happy Thanksgiving Day - A + B Problem
  2. AlertDialog(对话框)详解
  3. 在腾讯轻量云Linux上搭建 CSGO 服务器
  4. ECC算法推荐参数(256k1和256r1)
  5. PVCBOT【19号】漫舞者--折叠滑步机器人
  6. AlexNet、VGG、GoogLeNet、ReaNet、MobileNet、ShuffleNet和EfficientNet网络的亮点和创新之处
  7. 《白话C++》第3章 感受(一) 3.1 Hello world 经典版
  8. Zotero无法读取中文期刊元数据
  9. RuntimeError: CUDA out of memory. Tried to allocate 14.00 MiB linux跑深度学习爆显存问题
  10. Linux _ 文件系统的类型和结构