场景

es查询报错,报错如下:

trying to create too many buckets. must be less than or equal to: [10000] but was [10001].

问题分析

显示网上搜索了一番,大都给出了问题原因,那就是ES聚合查询的聚合桶查询默认为10000,查询超过的时候,就会报错,导致查询失败。由于Bucket aggregations查询操作比较消耗内存,如果聚集桶过多,频率较大时,很容易导致集群JVM内存不足,进而产生查询熔断。

我们看下官网描述,确实是这么回事:

问题复现

注意官网的这一句话:

Requests that attempt to return more than this limit will return an error.
翻译:试图返回超过此限制的请求将返回错误。

那么我们来验证一下,复现一下问题:

环境说明:本人采用的是es7.8.1的版本进行演示测试,使用postman进行测试

创建测试聚合桶查询的索引库(PUT请求)

localhost:9200/testbuckets
{
"mappings": {
"properties": {
"name": {
"type": "keyword"
},
"price": {
"type": "long"
},
"color": {
"type": "keyword"
},
"size": {
"type": "long"
},
"category": {
"type": "keyword"
},
"label": {
"type": "keyword"
},
"release_date": {
"type": "date"
}
}
}
} ====返回====
{
"acknowledged": true,
"shards_acknowledged": true,
"index": "testbuckets"
}

构建测试数据,为了模拟分桶数据,我将创建一些手机测试数据用于演示。

创建数据(PUT请求)

localhost:9200/testbuckets/_bulk
{"index":{}}
{"name":"小米13","price":3400,"color":"白色","size":6.21,"category":"小米","label":"高端","release_date":"2022-02-06"}
{"index":{}}
{"name":"小米13","price":3400,"color":"黑色","size":6.21,"category":"小米","label":"高端","release_date":"2022-02-06"}
{"index":{}}
{"name":"小米12","price":2400,"color":"黑色","size":6.21,"category":"小米","label":"快充","release_date":"2021-02-06"}
{"index":{}}
{"name":"苹果13","price":3400,"color":"黑色","size":6.21,"category":"苹果","label":"性能","release_date":"2022-02-06"}
{"index":{}}
{"name":"苹果14","price":2400,"color":"远峰蓝色","size":6.21,"category":"苹果","label":"性能","release_date":"2021-02-06"}
{"index":{}}
{"name":"华为Mate 50","price":5200,"color":"白色","size":6.21,"category":"华为","label":"鸿蒙OS","release_date":"2021-05-06"}
{"index":{}}
{"name":"华为Mate 50","price":5200,"color":"黑色","size":6.21,"category":"华为","label":"鸿蒙OS","release_date":"2021-05-06"}
{"index":{}}
{"name":"华为Mate 40 Pro","price":5900,"color":"黑色","size":6.21,"category":"华为","label":"商务","release_date":"2022-02-06"}
{"index":{}}
{"name":"华为Mate 40 Pro","price":5900,"color":"白色","size":6.21,"category":"华为","label":"商务","release_date":"2022-02-06"} ps:使用postman批量插入测试数据,最后一条记录后面需要换行,否则会插入失败

修改es最大分桶配置参数(PUT请求)

http://127.0.0.1:9200/_cluster/settings
{
"persistent": {
"search.max_buckets": 2 //为了演示,设值为2,官方默认此值为10000
}
}

构造聚合查询,在上面,我们创建了测试使用的手机索引库,此时,我们按照手机颜色进行数据聚合分组查询:

查询数据(GET请求)

http://127.0.0.1:9200/testbuckets/_search
{
"aggs": {
"by_color": { // 按照颜色合聚合
"terms": {
"field": "color" // 聚合字段
}
}
},
"size": 0 //不显示原始数据,只看分组数据
} ===返回结果===
{
"error": {
"root_cause": [
{
"type": "too_many_buckets_exception",
"reason": "Trying to create too many buckets. Must be less than or equal to: [2] but was [3]. This limit can be set by changing the [search.max_buckets] cluster level setting.",
"max_buckets": 2
}
],
"type": "search_phase_execution_exception",
"reason": "all shards failed",
"phase": "query",
"grouped": true,
"failed_shards": [
{
"shard": 0,
"index": "testbuckets",
"node": "UuMcBk37TNWHjY4hVtzyVA",
"reason": {
"type": "too_many_buckets_exception",
"reason": "Trying to create too many buckets. Must be less than or equal to: [2] but was [3]. This limit can be set by changing the [search.max_buckets] cluster level setting.",
"max_buckets": 2
}
}
]
},
"status": 503
}

可以看到错误已经复现了,为什么呢,因为我们刚才将search.max_buckets配置参数改成了2,而实际上我们的测试数据里,如果根据color来分桶查询,会有黑色,白色,远峰蓝色这3种颜色,查询结果超过了限制值,就报错了,就证明了官方的Requests that attempt to return more than this limit will return an error的说法

我们将search.max_buckets改大一点再看(PUT请求)

http://127.0.0.1:9200/_cluster/settings
{
"persistent": {
"search.max_buckets": 3
}
}
===返回结果===
{
"acknowledged": true,
"persistent": {
"search": {
"max_buckets": "3"
}
},
"transient": {}
}

再次执行查询(GET请求),就会发现不报错了。

http://127.0.0.1:9200/testbuckets/_search
{
"aggs": {
"by_color": { // 按照颜色合聚合
"terms": {
"field": "color" // 聚合字段
}
}
},
"size": 0 //不显示原始数据,只看分组数据
}
===返回结果===
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 9,
"relation": "eq"
},
"max_score": null,
"hits": []
},
"aggregations": {
"by_color": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "黑色",
"doc_count": 5
},
{
"key": "白色",
"doc_count": 3
},
{
"key": "远峰蓝色",
"doc_count": 1
}
]
}
}
}

解决方案

方案一

修改配置(PUT请求):

// 临时修改,es重启失效
http://127.0.0.1:9200/_cluster/settings
{"transient": {"search.max_buckets": 50000}} // 永久修改,esc重启依旧生效
http://127.0.0.1:9200/_cluster/settings
{"persistent": {"search.max_buckets": 50000}}

服务器上可使用curl命令:

// 临时修改,es重启失效
curl -X PUT "http://127.0.0.1:9200/_cluster/settings" -H 'Content-Type: application/json' -d '{"transient":{"search.max_buckets": 50000}}' // 永久修改,esc重启依旧生效
curl -X PUT -k "http://127.0.0.1:9200/_cluster/settings" -H 'Content-Type: application/json' -d '{"persistent":{"search.max_buckets": 1000000}}'
说明:es一些配置修改,有两种方式,上面我修改最大分桶参数使用到了persistent,二者区别如下。
transient 临时:这些设置在集群重启之前一直会生效。一旦整个集群重启,这些设置就会被清除。
persistent 永久:这些设置永久保存,除非再次被手动修改。是将修改持久化到文件中,重启之后也不影响。

弊端:由于Bucket aggregations查询操作比较消耗内存,如果聚集桶过多,频率较大时,很容易导致集群JVM内存不足,进而产生查询熔断,所以不能无限制的扩大分桶数参数,需要结合实际服务器能力与业务需求来考量一个合适的值。

方案二

整改业务,大多场景下,对于查询结果是想获取到自己想要的精确少量结果,es 默认设置 10000 的上限是有原因的,这块需要对你的服务器性能有一个评估,考虑你的 es 服务是否能撑得住这种大量的聚合计算,冒然扩大限制可能导致服务的崩溃。如果预计的 buckets 数量级别过大,就需要结合具体场景分析在查询层面进行优化。

比如还拿我上面的手机测试库来看,如果非要不改配置而实现查询不报错,那么我们可以这样来优化一下查询业务。

此处仅做个参考思路演示,具体实际生产场景需要结合具体业务考虑。

http://127.0.0.1:9200/testbuckets/_search
{"query":{
"match":{
"category":"小米" // 限制查询手机类别,缩小数据范围,此处以小米品牌为例
}
},
"aggs": {
"by_color": {
"terms": {
"field": "color"
}
}
},
"size": 0 //不显示原始数据,只看分组数据
} ===返回结果====
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 3,
"relation": "eq"
},
"max_score": null,
"hits": []
},
"aggregations": {
"by_color": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "黑色",
"doc_count": 2
},
{
"key": "白色",
"doc_count": 1
}
]
}
}
}

ES实战-trying to create too many buckets的更多相关文章

  1. es实战之数据导出成csv文件

    从es将数据导出分两步: 查询大量数据 将数据生成文件并下载 本篇主要是将第二步,第一步在<es实战之查询大量数据>中已讲述. csv vs excel excel2003不能超过6553 ...

  2. 1W字|40 图|硬核 ES 实战

    前言 上篇我们讲到了 Elasticsearch 全文检索的原理<别只会搜日志了,求你懂点检索原理吧>,通过在本地搭建一套 ES 服务,以多个案例来分析了 ES 的原理以及基础使用.这次我 ...

  3. es实战之查询大量数据

    背景 项目中已提供海量日志数据的多维实时查询,客户提出新需求:将数据导出. 将数据导出分两步: 查询大量数据 将数据生成文件并下载 本文主要探讨第一步,在es中查询大量数据或者说查询大数据集. es支 ...

  4. Spring Boot & ES 实战,值得参考!

    作者:废物大师兄 cnblogs.com/cjsblog/p/9756978.html 1. 前言 1.1. 集成方式 Spring Boot中集成Elasticsearch有4种方式: REST C ...

  5. Spark2.2+ES6.4.2(三十二):ES API之index的create/update/delete/open/close(创建index时设置setting,并创建index后根据avro模板动态设置index的mapping)

    要想通过ES API对es的操作,必须获取到TransportClient对象,让后根据TransportClient获取到IndicesAdminClient对象后,方可以根据IndicesAdmi ...

  6. 2017 ES GZ Meetup分享:Data Warehouse with ElasticSearch in Datastory

    以下是我在2017 ES 广州 meetup的分享 ppt:https://elasticsearch.cn/slides/11#page=22 摘要 ES最多使用的场景是搜索和日志分析,然而ES强大 ...

  7. ElasticStack系列之十六 & ElasticSearch5.x index/create 和 update 源码分析

    开篇 在ElasticSearch 系列十四中提到的问题即 ElasticStack系列之十四 & ElasticSearch5.x bulk update 中重复 id 性能骤降,继续这个问 ...

  8. es与hive整合

    在hive classpath中添加elasticsearch-hadoop.jar,以下方法任一种均可: 1.启动hiveserver2 前,在hive-site.xml文件中更改hive.aux. ...

  9. Ceph RGW 创建默认的pool

    使用Ceph-deploy完成RGW服务部署后(最好是在部署RGW服务前建立如下这些pool),使用sudo ceph osd lspools 命令,会发现RGW自动以默认参数创建了N个rgw相关的p ...

  10. manage account

    #!/bin/bash # #Delete_user - Automates the steps to remove an account # ############################ ...

随机推荐

  1. python爬虫学习——列表

    namelist = [] #定义一个空的列表 namelist1 = ["小张","小红","小李"] print(namelist1[0 ...

  2. 学习Java Day10

    今天学习了数组的相关知识

  3. 学习Java Day15

    今天学习了自定义类

  4. 认识Spring MVC-概念-小demo

    二:SpringMVC 异常码: 405:请求不允许 404:资源不存在 400:参数有问题 500:代码有问题 SpringMvc是Spring FrameWork提供的WEB组件,是目前的主流的实 ...

  5. ORACLE数据库起不来

    由于意外导致数据库无法启动 首先切换到oracle用户,查看profile文件. su - oracle cat .bash_profile 然后进入数据库,查看挂载上 sqlplus "/ ...

  6. js根据某个字段进行分组

    分组前数据: [ {"f1":"q","f2":"w","f3":"e",&qu ...

  7. 用C++ 弹奏武侠音乐:沧海一声笑

    前言: 参照网路代码,用编程语言来弹奏一首音乐,搞点轻松的 原文:点击此处 完整代码: 以下为Visual Stuido 2022测试可用,控制台程序.运行之后,会自动弹奏沧海一声笑,并且出现歌词.主 ...

  8. Spring Cloud Alibaba 整合 Seata 实现分布式事务

    在Spring Boot单体服务中,添加@Transactional注解就能实现事务.在单体服务中,执行事务都是在同一个数据库下进行.但是随着业务越来越复杂,数据量越来越大会进行分库分表.在微服务场景 ...

  9. Angular 利用路由快照实现tab

    1.定义路由快照 新建文件SimpleReuseStrategy.ts import { RouteReuseStrategy, DefaultUrlSerializer, ActivatedRout ...

  10. CF1738E Balance Addicts

    个人思路: \(sum_i\) 表示前 \(i\) 个数的前缀和,推一下式子可知是要选若干对 \(l_i,r_i\),使得 \(l_1 < l_2 <\dots < l_k \le ...