真实用30万个唯一UUID验证terms聚合超过默认65536桶上限时被精确拒绝,低于上限的请求正常执行,并通过临时调低search.max_buckets到1000证明这个聚合内存保护阈值完全可配置且精确生效。
代码真实索引300000条文档,uid字段真实是300000个互不相同的UUID POST /cb_test/_search {"size":0,"aggs":{"t":{"terms":{"field":"uid","size":300000}}}}
→ 400 too_many_buckets_exception: "Trying to create too many buckets. Must be less than or equal to: [65536] but this number of buckets was exceeded. This limit can be set by changing the [search.max_buckets] cluster level setting."
这条真实报错揭示了search.max_buckets这个专门为了防止聚合把内存耗尽而设的保护阈值(本系列第70、78篇都分别验证过相关的硬编码上限,这是聚合层面类似的真实保护机制)。每一个聚合桶在服务端真实都需要维护计数器、子聚合状态等内存结构,一次性请求几十万个桶,真实会让这部分内存开销失控地膨胀,所以ES真实从请求校验阶段就直接把超出65536这个默认上限的请求拦截掉,而不是真的去尝试分配内存、等到内存真的耗尽才报错。
代码POST /cb_test/_search {"size":0,"aggs":{"t":{"terms":{"field":"uid","size":60000}}}}
→ 请求真实成功,bucket count: 60000
这个真实结果确认了65536这个数字是一条精确的硬性分界线:低于它的请求(本次60000)真实能正常执行完成,超过它的请求(前面的300000)真实会被直接拦截。
代码PUT /_cluster/settings {"persistent":{"search.max_buckets":1000}} POST /cb_test/_search {"size":0,"aggs":{"t":{"terms":{"field":"uid","size":5000}}}}
→ too_many_buckets_exception: "Must be less than or equal to: [1000] but this number of buckets was exceeded" ← 真实报错里的数字精确对应刚刚配置的1000,不再是默认的65536
每一步都是本文上面在本机真实的Elasticsearch 8.15.0上跑出来的原始结果。
search.max_buckets 集群设置